📄 network.c
字号:
} else { /* default IPv4 */ inet_ntop(result->ai_family, &((struct sockaddr_in *)result->ai_addr)->sin_addr, hoststr, sizeof(hoststr)); } /* display host:ports */ display(MSDL_NOR,"Host: [ %s:%s ] ",hoststr,portstr); sock_server = socket(result->ai_family,result->ai_socktype,result->ai_protocol); if(sock_server == -1) { display(MSDL_ERR,"socket() error"); return -1; } /* Turn the socket to non-blocking socket, so we can timeout. */ fcntl(sock_server,F_SETFL,fcntl(sock_server,F_GETFL) | O_NONBLOCK); if(connect(sock_server,result->ai_addr,result->ai_addrlen) == -1) { /* failed not because it was non-blocking */ if(errno != EINPROGRESS) { display(MSDL_ERR,"connect() failed"); goto failed; } } for(;;) { /* init */ tv.tv_sec = 3; tv.tv_usec = 0; FD_ZERO(&set); FD_SET(sock_server,&set); ret = select(sock_server+1,NULL,&set,NULL,&tv); if(ret < 0) { /* select failed! */ display(MSDL_ERR,"select() failed"); goto failed; } else if(ret > 0) break; else if(try_count > 5) { /* 12 sec */ display(MSDL_ERR,"timeout!\n"); goto failed; } display(MSDL_NOR,"."); try_count++; } /* Turn the socket to blocking, as we don't need it. */ fcntl(sock_server, F_SETFL, fcntl(sock_server,F_GETFL) & ~O_NONBLOCK); display(MSDL_NOR," connected!\n"); freeaddrinfo(result); return sock_server; /* failure */ failed: if(sock_server) close(sock_server); if(result) freeaddrinfo(result); return -1;}/* * prepare listning socket opening 'port'. * protocol family can be specified by 'family' * * return value : sock ... success * -1 ... failure */int waiting_socket(int family,int port){ int sock; int ret; char portstr[8]; struct addrinfo hints,*result = NULL; if(port < 0 || 0xffff < port) { display(MSDL_ERR,"internal: invalid port number\n"); goto failed; } memset(portstr,0,8); snprintf(portstr,7,"%d",port); memset(&hints,0,sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(NULL,portstr,&hints,&result); if(ret != 0) { perror("getaddrinfo() failed"); goto failed; } sock = socket(result->ai_family,result->ai_socktype,result->ai_protocol); if(sock < 0) { perror("socket() failed"); goto failed; } ret = bind(sock,(struct sockaddr *)result->ai_addr,result->ai_addrlen); if(ret < 0) { perror("bind() failed"); goto failed; } ret = listen(sock,1); if(ret < 0) { perror("listen() failed"); goto failed; } freeaddrinfo(result); return sock; failed: if(result) freeaddrinfo(result); return -1;}/* * accept connectoin from client. * return value : sock .. success * -1 .. failure */int accept_connection(int wait_sock){ struct sockaddr_storage ss; socklen_t sslen; int sock; int ret; ret = sock_check_data(wait_sock,15); if(ret <= 0) { return -1; } sslen = sizeof(ss); sock = accept(wait_sock,(struct sockaddr *)&ss,&sslen); if(sock == -1) { perror("accept() failed"); return -1; } return sock;}/* * this is wrapper for recv, and has timeout. * return value: length --> success * -1 --> error/timeout * 0 --> eof */int xrecv(int sock,void *buf,size_t count){ fd_set fds; struct timeval tv; int retval; tv.tv_sec = XRECV_TIMEOUT; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock,&fds); retval = select(sock + 1,&fds,NULL,NULL,&tv); if(retval == -1) { /* select() Error (system call error) */ perror("select() failed\n"); goto failed; } else if(!retval) { /* No data arrived (error)*/ display(MSDL_ERR,"timeout!! could not receive data\n"); goto failed; } retval = recv(sock,buf,count,0); if(retval < 0) { /* recv() Error (system call error) */ perror("recv() failed\n"); goto failed; } return retval; failed: return -1;}/* * send() wrapper */int xsend(int sock,void *buf,size_t count){ return (send(sock,buf,count,0));}int sock_check_data(int sock,int timeout){ fd_set fds; struct timeval tv; int ret; FD_ZERO(&fds); FD_SET(sock,&fds); tv.tv_sec = timeout; tv.tv_usec = 0; ret = select(sock + 1,&fds,NULL,NULL,&tv); if(ret == -1) { perror("stream_check_data: select() failed"); } return ret;}int stream_check_data(struct stream_t *stream,int timeout){ if(stream->netsock->data_len) { return 1; } return sock_check_data(stream->netsock->sock,timeout);}/* * recv count bytes of data from sock to buf. * this is only used when count bytes of data are * supposed to come from sock. * this function must be used when 'count' bytes are guaranteed * to be received. * return value: length --> success. * 0 --> eof * -1 --> timeout or error (fatal) */int get_data(int sock,void *buf,size_t count){ int len; size_t total = 0; while(total < count) { /* more data to recv. */ len = xrecv(sock,(uint8_t *)buf + total,count - total); if(len < 0) { /* Error. timeout, syscall error */ goto failed; } else if(len == 0) { /* EOF */ display(MSDL_ERR,"met EOF when %d bytes are to come\n",count); goto meteof; } total += len; } return total; meteof: return 0; failed: return -1;}/* * read 'size' bytes from *resources*. * * *resources* are : [in this order] * 1. netsock->buffer (data which came with http header) * 2. netsock->sock (network) * * return value : size which read. * -1 if get_data failed. */int read_data(struct stream_t *stream, void *buffer, size_t size){ struct netsock_t *netsock = stream->netsock; int len; /* how many bytes are stored in 'buffer' */ int ret; /*printf("read_data size = %d netsock->data_len = %d," " netsock->buffer_pos = %d\n", size,netsock->data_len, netsock->buffer_pos);*/ len = 0; if(netsock->data_len) { /* there is a data to read in netsock->buffer */ len = (size < netsock->data_len) ? size : netsock->data_len; /* smaller */ memcpy((uint8_t *)buffer,netsock->buffer + netsock->buffer_pos,len); netsock->buffer_pos += len; netsock->data_len -= len; if(netsock->data_len == 0) { netsock->buffer_pos = 0; } } if(len < size) { ret = get_data(netsock->sock,(uint8_t *)buffer + len, size - len); if(ret < 0) { /* get_data mets timeout/error */ return -1; } else { len += ret; } } return len;}/* * different from read_data, this function's 3ed argument is * max byte to read from stream. * return value: len ... bytes stored in buffer * 0 ... * -1 ... timeout */int recv_data(struct stream_t *stream,void *buffer,size_t max){ struct netsock_t *netsock = stream->netsock; int len; /* how many bytes are stored in 'buffer' */ int ret; if((len = netsock->data_len)) { /* there is a data to read in netsock->buffer */ len = (max < len) ? max : len; /* smaller */ memcpy((uint8_t *)buffer,netsock->buffer + netsock->buffer_pos,len); netsock->buffer_pos += len; netsock->data_len -= len; if(netsock->data_len == 0) { netsock->buffer_pos = 0; } } /* still network stream can be read. */ if(len < max) { if(!len || sock_check_data(netsock->sock,0)) {/* just check there are some data now */ ret = xrecv(netsock->sock,(uint8_t *)buffer + len,max - len); if(ret < 0) { return -1; } else { len += ret; /* when sock was shut down by server and nothing was in buffer, len == 0 and ret == 0 so return 0, this is OK. */ } } } return len;}/* * push data to netsock->buffer so that the data can be read later */int stream_data_push_back(struct stream_t *stream,void *buffer,int size){ struct netsock_t *netsock = stream->netsock; if(netsock->data_len) { memmove(netsock->buffer + netsock->buffer_pos + size, netsock->buffer + netsock->buffer_pos, netsock->data_len); } memcpy(netsock->buffer + netsock->buffer_pos,buffer,size); netsock->data_len += size; return (netsock->data_len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -