Socket not working for iPhone SDK 3.0+ - iphone

My code was working absolutely fine before the launch of iPhone SDK 3.0 , I am using socket functions to send data and receive data. What changes must i make to make it compatible for 3.0+.
-(int)InitSocket:(int)nPort: (NSString*)sServer{
if(sServer == nil)
{
return -1;
}
m_nPort = nPort;
sServerAddress = sServer;
const char* pServer = nil;
pServer = [sServer cStringUsingEncoding:NSASCIIStringEncoding];
m_nSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in servAddr;
memset(&servAddr, 0 , sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(pServer);
servAddr.sin_port = htons(m_nPort);
pfd.fd = m_nSock;
pfd.events = POLLIN | POLLERR| POLLHUP | POLLNVAL;
pfd.revents = 0;
m_nTimeout = -1;
int f = fcntl(m_nSock, F_GETFL, 0);
fcntl(m_nSock, F_SETFL, f | O_NONBLOCK |O_NDELAY);
int opt = 1;
setsockopt(m_nSock, SOL_SOCKET, SO_KEEPALIVE, (const void*)&opt,(socklen_t)sizeof(opt));
struct timeval timeout;
fd_set wset;
FD_ZERO(&wset);
FD_SET(m_nSock, &wset);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
return 0;
}
This Code for sending data
-(int)SendData:(size_t) nSize: (NSString*) buffer{
int nTotalSent = 0;
const char *pSend = [buffer cStringUsingEncoding:NSASCIIStringEncoding];
while(nTotalSent != nSize)
{
int nSent = send(m_nSock, (const void*)pSend+nTotalSent, nSize-nTotalSent, 0);
if(nSent == -1)
{
return nSent;
}
nTotalSent += nSent;
}
return nTotalSent;
}
Will the above code works in iPhone SDK 3.0+ , what changes i need to employ to make it work.
Thanks

You could start by properly checking for errors. All those functions that you use return an error code if something goes wrong and you will never know.

Related

TCP socket server using in6addr_any, the client can't connect use c, just using local ipv6

TCP socket server address using in6addr_any, the client can't connect
(using code 1), but using local ipv6 "fc00::2a4:1ff:fe15:7031", the client can connect (using code 2). The client and server are on two tasks of the same PC. Another pc can ping6 ipv6 "fc00::2a4:1ff:fe15:7031" successfully. But now, I just want to use code 1 instead of code 2 in the client.c and server.c on the same pc. What should I do?
a part code of server.c:
int ret = 0;
int fd;
unsigned int addrPort = tcp_port;
char addrIp[] = "fc00::2a4:1ff:fe15:7031";
fd = socket(AF_INET6, SOCK_STREAM, 0);
if( -1 == fd)
{
return -1;
}
memset_s(serv_addr, sizeof(struct sockaddr_in6), 0x0, sizeof(struct sockaddr_in6));
serv_addr->sin6_family = AF_INET6;
serv_addr->sin6_port = htons(7770);
serv_addr->sin6_len = sizeof(struct sockaddr_in6);
inet_pton(AF_INET6, addrIp, &serv_addr->sin6_addr);
// serv_addr->sin6_addr = in6addr_any;
ret = bind(fd, serv_addr, sizeof(struct sockaddr_in6));
if(0 != ret )
{
close(fd);
return -1;
}
ret = listen(fd, 1);
if(0 != ret )
{
close(fd);
return -1;
}
*server_fd = fd;
return VOS_OK;
code 1:
serv_addr->sin6_addr = in6addr_any;
code 2:
inet_pton(AF_INET6, addrIp, &serv_addr->sin6_addr);

How to resolve the Mac address for an IP address under kernel module developing?

I want to build a tcp package in a kernel module and send it to another host by IP address using function dev_queue_xmit(skb). But I don't want to fill the Mac address manually by hand. The following is code for package producing.
Some kernel functions call eth_rebuild_header(skb) to rebuild Mac header. However, in my case, it hangs my computer after being called. Google results answers that arp_find will crash the OS if the arp cache contains not entry for that IP address. But I'm sure the it exists in the arp cache as printed by shell command "arp -v".
static int build_and_xmit_tcp(char * eth, u_char * smac, u_char * dmac,
u_long sip, u_long dip,
u_short sport, u_short dport,
u_char * pkt, int pkt_len,
int syn, int ack, int fin,
__be32 seq, __be32 seq_ack)
{
struct sk_buff * skb = NULL;
struct net_device * dev = NULL;
struct ethhdr * ethdr = NULL;
struct iphdr * iph = NULL;
struct tcphdr * tcph = NULL;
u_char * pdata = NULL;
if(NULL == smac || NULL == dmac)
goto out;
if(NULL == (dev= dev_get_by_name(&init_net, eth)))
goto out;
skb = alloc_skb(pkt_len + sizeof(struct iphdr) + sizeof(struct tcphdr) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
if(NULL == skb)
goto out;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->priority = 0;
skb_set_network_header(skb, 0);
skb_put(skb, sizeof(struct iphdr));
skb_set_transport_header(skb, sizeof(struct iphdr));
skb_put(skb, sizeof(struct tcphdr));
pdata = skb_put(skb, pkt_len);
{
if(NULL != pkt)
memcpy(pdata, pkt, pkt_len);
}
tcph = tcp_hdr(skb);
memset(tcph, 0, sizeof(struct tcphdr));
tcph->source = sport;
tcph->dest = dport;
tcph->doff=5;
tcph->seq = htonl(seq);
tcph-> ack_seq= htonl( seq_ack);
tcph->psh = pkt_len>0? 1:0;
tcph ->fin = fin;
tcph->ack = ack;
tcph->syn=syn;
tcph->window=__constant_htons (65535);
skb->csum = 0;
tcph->check = 0;
iph = ip_hdr(skb);
iph->version = 4;
iph->ihl = sizeof(struct iphdr)>>2;
iph->frag_off = 0;
iph->protocol = IPPROTO_TCP;
iph->tos = 0;
iph->daddr = dip;
iph->saddr = sip;
iph->ttl = 0x40;
iph->tot_len = __constant_htons(skb->len);
iph->check = 0;
iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);
skb->csum = skb_checksum(skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);
tcph->check = csum_tcpudp_magic(sip, dip, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
skb_push(skb, 14);
skb_set_mac_header(skb, 0);
ethdr = (struct ethhdr *)eth_hdr(skb);
// memcpy(ethdr->h_dest, dmac, ETH_ALEN);
// memcpy(ethdr->h_source, smac, ETH_ALEN);
ethdr->h_proto = __constant_htons(ETH_P_IP);
// arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
// dst_ha, dev->dev_addr, NULL);
eth_rebuild_header(skb); // kernel hang....
if(0 > dev_queue_xmit(skb)) {
dev_put (dev);
kfree_skb (skb);
}
return(NF_ACCEPT);
out:
dev_put (dev);
kfree_skb (skb);
return(NF_ACCEPT);
}
static int __init myhook_init(void)
{
printk("=========insert module......\n");
build_and_xmit_tcp(ETH_O, GWMAC_O, DMAC, in_aton(GWIP_O), in_aton(DIP), htons(8888), htons(DPORT),
"", 0,
1, 0, 0, 0, 0);
}
static void __exit myhook_fini(void)
{
printk("=========rmmod ......\n");
}
module_init(myhook_init);
module_exit(myhook_fini);
Google gives me some other solution. They say arp_ioctl can resolve the Mac address. However, the fact is that, arp_ioctl is compiled statically into vmlinuz, which is not exported as a symbol to other modules.
int arp_get(char *ifname, char *ipStr)
{
struct arpreq req;
struct sockaddr_in *sin;
int ret = 0;
int sock_fd = 0;
struct net_device * dev = NULL;
printk("arp ---- \n");
if(NULL == (dev= dev_get_by_name(&init_net, ifname))){
dev_put (dev);
printk("error dev get \n");
return -1;
}
struct net *net_arp = dev_net(dev);
memset(&req, 0, sizeof(struct arpreq));
sin = (struct sockaddr_in *)&req.arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in_aton(ipStr);
strncpy(req.arp_dev, ifname, 15);
ret = arp_ioctl(net_arp, SIOCGARP, &req); // can't be called
unsigned char *hw = (unsigned char *)req.arp_ha.sa_data;
printk("%#x-%#x-%#x-%#x-%#x-%#x\n", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
return 0;
}
Maybe I need make a socket structure, and try some upper functions based on a socket. But how to do it...
kernel version : 2.6.32
os version: ubuntu 9.10
gcc version : 4.41
int ip_xmit(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
struct tcphdr *tcph = tcp_hdr(skb);
printk("dst is %d\n", skb->_skb_dst);
int err;
// err = ip_route_input(skb, iph->daddr, iph->saddr, 0, skb->dev);
struct rtalbe *rt;
{
struct flowi fl = { .oif = 0,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr,
.tos = 0 } },
.proto = IPPROTO_TCP,
.flags = 0,
.uli_u = { .ports =
{ .sport = tcph->source,
.dport = tcph->dest } } };
if (err = ip_route_output_key(&init_net, &rt, &fl))
return err;
printk("err is %d\n", err);
}
skb_dst_set(skb, rt);
if(0 > ip_local_out(skb)) {
printk("dev error\n");
kfree_skb (skb);
return -1;
}
return 0;
}
function ip_route_output_key can obtain the route destination, and ip_local_out deliver the skb out.

Non-blocking sock_recvmsg() - is it possible?

I have the following function calling it out of a kernel thread in a kernel module:
static int ksocket_receive(struct socket* sock, struct sockaddr_in* addr, unsigned char* buf, int len)
{
struct msghdr msg;
mm_segment_t oldfs;
int size = 0;
if (sock->sk == NULL) return 0;
msg.msg_flags = 0;
msg.msg_name = addr;
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iocb = NULL;
oldfs = get_fs();
set_fs(KERNEL_DS);
size = sock_recvmsg(sock,&msg,len,msg.msg_flags);
set_fs(oldfs);
return size;
}
It blocks inside in sock_recvmsg(). Is there a way to have non-blocking version of sock_recvmsg()?
Something similar to MSG_DONTWAIT and O_NONBLOCK flags for the equivalent in User Space - recvmsg()...

UDP broadcast being sent, but not received (yes, again)

I have a question seemingly the same as this one, yet having checked that and others I can't see the difference.
I have an app that receives UDP broadcasts. It loops back on itself properly, and can on the same machine receive from another app. However, when I try to receive from an external GoPro Hero4 Black,
I can send and receive TCP with the camera within the same app
Another app on the same machine can receive the UDP broadcasts from the camera
This app sees nothing
I checked for properly using INADDR_ANY, and it's being done in the code. Given the machine does receive the packets, and the app itself can do TCP with the camera, the error has to be in the UDP receive code, yet that works between apps on the same machine.
Question: What could cause this behavior?
My belief is the problem is in my understanding of UDP broadcast receive, but nevertheless, in response to a comment, here's code. This initializes the receiver:
int yudpsocket_server(const char *addr,int port) {
//create socket
int socketfd=socket(AF_INET, SOCK_DGRAM, 0);
int reuseon = 1;
int r = -1;
//bind
struct sockaddr_in serv_addr;
serv_addr.sin_len = sizeof(struct sockaddr_in);
serv_addr.sin_family = AF_INET;
if (addr == NULL || strlen(addr) == 0 || strcmp(addr, BROADCAST_IP) == 0) {
r = setsockopt( socketfd, SOL_SOCKET, SO_BROADCAST, &reuseon, sizeof(reuseon) );
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
} else {
r = setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
serv_addr.sin_addr.s_addr = inet_addr(addr);
serv_addr.sin_port = htons(port);
memset( &serv_addr, '\0', sizeof(serv_addr));
}
if (r == -1) {
return -1;
}
r = bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (r==0) {
return socketfd;
} else {
return -1;
}
}
And this does the receive:
int yudpsocket_receive(int socket_fd, char *outdata, int expted_len, char *remoteip, int* remoteport) {
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
memset(&cli_addr, 0x0, sizeof(struct sockaddr_in));
int len = (int)recvfrom(socket_fd, outdata, expted_len, 0, (struct sockaddr *)&cli_addr, &clilen);
char *clientip = inet_ntoa(cli_addr.sin_addr);
memcpy(remoteip, clientip, strlen(clientip));
*remoteport = cli_addr.sin_port; // Maybe not right - s.b. ntohs()?
return len;
}

Recv fails when using python sendall in iOS project

I have a python server that is trying to send a binary file to a client on iOS but 90% of the time the file is incomplete. The receive call on the client fails after receiving about 80% of the file.
This is basically how it's setup.
Server
class ForkingTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
f = open(TEST_FILE_NAME, 'rb')
file_data = f.read()
self.request.sendall(file_data)
f.close()
class ForkingTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
pass
if __name__ == '__main__':
try:
server = ForkingTCPServer(('0.0.0.0', 9000), ForkingTCPRequestHandler)
except socket.error as e:
sys.exit(1)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
sys.exit(0)
This code works outside of our iOS project (entire file is received)
int receiveFile() {
/* ... */
/* Receive file */
tempBuf = (char*) malloc(sizeof(char)*fileLen);
totalRecv = 0;
recvBytes = 0;
while (totalRecv < fileLen) {
recvBytes = recv(s, tempBuf+totalRecv, 1<<14, 0);
if (recvBytes < 0) {
free(tempBuf);
close(s);
return -1;
}
totalRecv += recvBytes;
}
close(s);
return 0;
}
int connectToServerWithHostname(char *hostname, char *port) {
/* ... */
memset(&targetAddr, 0, sizeof(targetAddr));
targetAddr.sin_family = AF_INET;
targetAddr.sin_port = htons(atoi(port));
bcopy(hostdetails->h_addr, (char *)&targetAddr.sin_addr, hostdetails->h_length);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (socket < 0) {
return -1;
}
rc = connect(sock, (struct sockaddr *)&targetAddr, sizeof(targetAddr));
if (rc < 0) {
close(sock);
return -1;
}
return sock;
}
int main(int argc, char **argv) {
assert(!receiveFile());
return 0;
}
But this equivalent code inside our iOS project fails (partial receive). Even though I'm connecting and receiving the same way as the code above.
while (totalRecv < ntohl(symProcPacket.totalDataLen)) {
recvBytes = recv(s, tempBuf+totalRecv, DEFAULT_SENDRECVSIZE, DEFAULT_SENDRECV_FLAGS);
if (recvBytes < 0) {
debug("Error, could not receive file\n");
free(tempBuf);
errorType = kSymClientErrorReceiving;
goto errorImporting;
}
totalRecv += recvBytes;
printf("Received: %d/%d\n", totalRecv, ntohl(symProcPacket.totalDataLen));
}
Any ideas on why this is failing?
Are sockets different in an iOS project or something?