Socket_Tsocket_create(void*port){intsocket;Socket_TS=NULL;Port_Tp=port;ASSERT(port);switch(p->family){caseAF_UNIX:socket=create_unix_socket(p->pathname,p->type,p->timeout);break;caseAF_INET:socket=create_socket(p->hostname,p->port,p->type,p->timeout);break;default:LogError("Invalid Port Protocol family\n");returnNULL;}if(socket<0){LogError("socket_create: Could not create socket -- %s\n",STRERROR);}else{NEW(S);S->socket=socket;S->type=p->type;S->port=p->port;S->timeout=p->timeout;S->connection_type=TYPE_LOCAL;if(p->family==AF_UNIX){S->host=Str_dup(LOCALHOST);}else{S->host=Str_dup(p->hostname);}if(p->SSL.use_ssl&&!socket_switch2ssl(S,p->SSL)){socket_free(&S);returnNULL;}S->Port=port;}returnS;}
intcreate_socket(constchar*hostname,intport,inttype,inttimeout){ints,status;structsockaddr_insin;structsockaddr_in*sa;structaddrinfohints;structaddrinfo*result;ASSERT(hostname);memset(&hints,0,sizeof(structaddrinfo));hints.ai_family=AF_INET;if((status=getaddrinfo(hostname,NULL,&hints,&result))!=0){LogError("Cannot translate '%s' to IP address -- %s\n",hostname,status==EAI_SYSTEM?STRERROR:gai_strerror(status));return-1;}if((s=socket(AF_INET,type,0))<0){LogError("Cannot create socket -- %s\n",STRERROR);freeaddrinfo(result);return-1;}sa=(structsockaddr_in*)result->ai_addr;memcpy(&sin,sa,result->ai_addrlen);sin.sin_family=AF_INET;sin.sin_port=htons(port);freeaddrinfo(result);if(!Net_setNonBlocking(s)){LogError("Cannot set nonblocking socket -- %s\n",STRERROR);gotoerror;}if(fcntl(s,F_SETFD,FD_CLOEXEC)==-1){LogError("Cannot set socket close on exec -- %s\n",STRERROR);gotoerror;}if(do_connect(s,(structsockaddr*)&sin,sizeof(sin),timeout)<0){gotoerror;}returns;error:Net_close(s);return-1;}
/*
* Do a non blocking connect, timeout if not connected within timeout milliseconds
*/staticintdo_connect(ints,conststructsockaddr*addr,socklen_taddrlen,inttimeout){interror=0;structpollfdfds[1];error=connect(s,addr,addrlen);if(error==0){return0;}elseif(errno!=EINPROGRESS){LogError("Connection failed -- %s\n",STRERROR);return-1;}fds[0].fd=s;fds[0].events=POLLIN|POLLOUT;error=poll(fds,1,timeout);if(error==0){LogError("Connection timed out\n");return-1;}elseif(error==-1){LogError("Poll failed -- %s\n",STRERROR);return-1;}if(fds[0].events&POLLIN||fds[0].events&POLLOUT){socklen_tlen=sizeof(error);if(getsockopt(s,SOL_SOCKET,SO_ERROR,&error,&len)<0){LogError("Cannot get socket error -- %s\n",STRERROR);return-1;}elseif(error){errno=error;LogError("Socket error -- %s\n",STRERROR);return-1;}}else{LogError("Socket not ready for I/O\n");return-1;}return0;}
上記の176行目の epoll でタイムアウトした場合は 177行目の if (error == 0) が成立してエラーで抜けることになります。
intsocket_write(Socket_TS,void*b,size_tsize){ssize_tn=0;void*p=b;ASSERT(S);while(size>0){if(S->ssl){n=send_ssl_socket(S->ssl,p,size,S->timeout);}else{if(S->type==SOCK_DGRAM)n=udp_write(S->socket,p,size,S->timeout);elsen=sock_write(S->socket,p,size,S->timeout);}if(n<=0)break;p+=n;size-=n;}if(n<0){/* No write or a partial write is an error */return-1;}return(int)(p-b);}
char*socket_readln(Socket_TS,char*s,intsize){intc;unsignedchar*p=(unsignedchar*)s;ASSERT(S);while(--size&&((c=socket_read_byte(S))>0)){// Stop when \0 is read
*p++=c;if(c=='\n')break;}*p=0;if(*s)returns;returnNULL;}
/*
* Fill the internal buffer. If an error occurs or if the read
* operation timed out -1 is returned.
* @param S A Socket object
* @param timeout The number of milliseconds to wait for data to be read
* @return TRUE (the length of data read) or -1 if an error occured
*/staticintfill(Socket_TS,inttimeout){intn;S->offset=0;S->length=0;if(S->type==SOCK_DGRAM)timeout=500;if(S->ssl){n=recv_ssl_socket(S->ssl,S->buffer+S->length,RBUFFER_SIZE-S->length,timeout);}else{n=(int)sock_read(S->socket,S->buffer+S->length,RBUFFER_SIZE-S->length,timeout);}if(n>0){S->length+=n;}elseif(n<0){return-1;}elseif(!(errno==EAGAIN||errno==EWOULDBLOCK))// Peer closed connection
return-1;returnn;}