std::string get_socket_error() { #ifdef _WIN32 return get_socket_error(WSAGetLastError()); #else return get_socket_error(errno); #endif }
bool net::socket::connect(type type, const socket_address& addr, int timeout) { // Create socket. if (!create(addr.ss_family, type)) { return false; } // Connect. if ((::connect(_M_fd, reinterpret_cast<const struct sockaddr*>(&addr), addr.size()) < 0) && (errno != EINPROGRESS)) { close(); return false; } if (timeout != 0) { if (!wait_writable(timeout)) { close(); return false; } int error; if ((!get_socket_error(error)) || (error != 0)) { close(); return false; } } return true; }
int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd) { #ifdef RKTIO_SYSTEM_UNIX return rktio_poll_read_ready(rktio, rfd); #endif #ifdef RKTIO_SYSTEM_WINDOWS { rktio_socket_t s = rktio_fd_socket(rktio, rfd); DECL_SOCK_FDSET(readfds); DECL_SOCK_FDSET(exnfds); struct timeval time = {0, 0}; int sr; INIT_DECL_SOCK_WR_FDSET(readfds); INIT_DECL_SOCK_ER_FDSET(exnfds); RKTIO_SOCK_FD_ZERO(readfds); RKTIO_SOCK_FD_SET(s, readfds); RKTIO_SOCK_FD_ZERO(exnfds); RKTIO_SOCK_FD_SET(s, exnfds); sr = select(RKTIO_SOCKS(s + 1), readfds, NULL, exnfds, &time); if (sr == -1) { get_socket_error(); return RKTIO_POLL_ERROR; } else if (sr) return RKTIO_POLL_READY; else return 0; } #endif }
int s_poll_error(s_poll_set *fds, int fd) { /* error conditions are signaled as read, but apparently *not* in Winsock: * http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx */ if(!FD_ISSET(fd, fds->orfds) && !FD_ISSET(fd, fds->oxfds)) return 0; return get_socket_error(fd); /* check if it's really an error */ }
int s_poll_error(s_poll_set *fds, int fd) { unsigned int i; for(i=0; i<fds->nfds; i++) if(fds->ufds[i].fd==fd) return fds->ufds[i].revents&(POLLERR|POLLNVAL) ? get_socket_error(fd) : 0; return 0; /* not listed in fds */ }
int s_connect(CLI *c, SOCKADDR_UNION *addr, socklen_t addrlen) { int error; char *dst; dst=s_ntop(addr, addrlen); s_log(LOG_INFO, "s_connect: connecting %s", dst); if(!connect(c->fd, &addr->sa, addrlen)) { s_log(LOG_NOTICE, "s_connect: connected %s", dst); str_free(dst); return 0; /* no error -> success (on some OSes over the loopback) */ } error=get_last_socket_error(); if(error!=S_EINPROGRESS && error!=S_EWOULDBLOCK) { s_log(LOG_ERR, "s_connect: connect %s: %s (%d)", dst, s_strerror(error), error); str_free(dst); return -1; } s_log(LOG_DEBUG, "s_connect: s_poll_wait %s: waiting %d seconds", dst, c->opt->timeout_connect); s_poll_init(c->fds); s_poll_add(c->fds, c->fd, 1, 1); switch(s_poll_wait(c->fds, c->opt->timeout_connect, 0)) { case -1: error=get_last_socket_error(); s_log(LOG_ERR, "s_connect: s_poll_wait %s: %s (%d)", dst, s_strerror(error), error); str_free(dst); return -1; case 0: s_log(LOG_ERR, "s_connect: s_poll_wait %s:" " TIMEOUTconnect exceeded", dst); str_free(dst); return -1; default: error=get_socket_error(c->fd); if(error) { s_log(LOG_ERR, "s_connect: connect %s: %s (%d)", dst, s_strerror(error), error); str_free(dst); return -1; } if(s_poll_canwrite(c->fds, c->fd)) { s_log(LOG_NOTICE, "s_connect: connected %s", dst); str_free(dst); return 0; /* success */ } s_log(LOG_ERR, "s_connect: s_poll_wait %s: internal error", dst); str_free(dst); return -1; } return -1; /* should not be possible */ }
int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode) { rktio_socket_t s = rktio_fd_socket(rktio, rfd); if (shutdown(s, ((mode == RKTIO_SHUTDOWN_READ) ? RKTIO_SHUT_RD : RKTIO_SHUT_WR))) { get_socket_error(); return 0; } return 1; }
int RPC_CLIENT::init_poll() { fd_set read_fds, write_fds, error_fds; struct timeval tv; int retval; FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_ZERO(&error_fds); FD_SET(sock, &read_fds); FD_SET(sock, &write_fds); FD_SET(sock, &error_fds); BOINCTRACE("RPC_CLIENT::init_poll sock = %d\n", sock); tv.tv_sec = tv.tv_usec = 0; select(FD_SETSIZE, &read_fds, &write_fds, &error_fds, &tv); retval = 0; if (FD_ISSET(sock, &error_fds)) { retval = ERR_CONNECT; } else if (FD_ISSET(sock, &write_fds)) { retval = get_socket_error(sock); if (!retval) { BOINCTRACE("RPC_CLIENT::init_poll connected to port %d\n", ntohs(addr.sin_port)); retval = boinc_socket_asynch(sock, false); if (retval) { BOINCTRACE("asynch error: %d\n", retval); return retval; } return 0; } else { BOINCTRACE("init_poll: get_socket_error(): %d\n", retval); } } if (dtime() > start_time + timeout) { BOINCTRACE("RPC_CLIENT init timed out\n"); return ERR_CONNECT; } if (retval) { if (retry) { boinc_close_socket(sock); retval = boinc_socket(sock); retval = boinc_socket_asynch(sock, true); retval = connect(sock, (const sockaddr*)(&addr), sizeof(addr)); BOINCTRACE("RPC_CLIENT::init_poll attempting connect\n"); return ERR_RETRY; } else { return ERR_CONNECT; } } return ERR_RETRY; }
rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd) { #ifdef RKTIO_SYSTEM_UNIX return rktio_dup(rktio, rfd); #endif #ifdef RKTIO_SYSTEM_WINDOWS rktio_socket_t s = rktio_fd_socket(rktio, rfd); rktio_socket_t nsocket; intptr_t rc; WSAPROTOCOL_INFO protocolInfo; rc = WSADuplicateSocket(s, GetCurrentProcessId(), &protocolInfo); if (rc) { get_socket_error(); return NULL; } nsocket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &protocolInfo, 0, WSA_FLAG_OVERLAPPED); if (nsocket == INVALID_SOCKET) { get_socket_error(); return NULL; } return rktio_system_fd(rktio, nsocket, rktio_fd_modes(rktio, rfd) | RKTIO_OPEN_OWN); #endif }
static int udp_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){ belle_sip_udp_channel_t *chan=(belle_sip_udp_channel_t *)obj; int err; struct sockaddr_storage addr; socklen_t addrlen=sizeof(addr); belle_sip_socket_t sock=belle_sip_source_get_socket((belle_sip_source_t*)chan); err=recvfrom(sock,buf,buflen,0,(struct sockaddr*)&addr,&addrlen); if (err==-1 && get_socket_error()!=BELLESIP_EWOULDBLOCK){ belle_sip_error("Could not receive UDP packet: %s",belle_sip_get_socket_error_string()); return -errno; } return err; }
int check_connection_completion(int fd) { struct pollfd pfd; int retval; pfd.fd = fd; pfd.events = POLLOUT; do { retval = poll(&pfd, 1, 0); } while (retval < 0 && errno == EINTR); if (retval == 1) { return get_socket_error(fd); } else if (retval < 0) { return errno; } else { return EAGAIN; } }
bool wsa_send_empty(socket_t fd, WSAOVERLAPPED& ovl) { DWORD bytes = 0; WSABUF ws_buf = { 0, &s_zero }; memset(&ovl, 0, sizeof(ovl)); int ret = WSASend(fd, &ws_buf, 1, &bytes, 0, &ovl, nullptr); if (ret == 0) { return true; } else if (ret == SOCKET_ERROR) { int err = get_socket_error(); if (err == WSA_IO_PENDING) { return true; } } return false; }
NameResolver(const char *host, tcp_port port) { addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; std::stringstream port_str; // to_string in unavailable in MinGW. port_str << port; int result = getaddrinfo(host, port_str.str().c_str(), &hints, &addrs); if (result != 0) { std::stringstream msg; msg << "Unable to resolve host '" << host << "': " << get_socket_error(result); throw host_resolve_error(msg.str()); } if (addrs == nullptr) { std::stringstream msg; msg << "Unable to resolve host '" << host << "': no matching host found"; throw host_resolve_error(msg.str()); } }
int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error) { #ifdef RKTIO_SYSTEM_UNIX if (set_error) return rktio_close(rktio, rfd); else { rktio_close_noerr(rktio, rfd); return 1; } #endif #ifdef RKTIO_SYSTEM_WINDOWS rktio_socket_t s = rktio_fd_socket(rktio, rfd); int err; UNREGISTER_SOCKET(s); err = closesocket(s); if (!err) get_socket_error(); free(rfd); return !err; #endif }
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len) { rktio_socket_t s = rktio_fd_socket(rktio, rfd); int rn; do { rn = recv(s, buffer, len, 0); } while ((rn == -1) && NOT_WINSOCK(errno == EINTR)); if (rn > 0) return rn; else if (rn == 0) return RKTIO_READ_EOF; else { int err = SOCK_ERRNO(); if (WAS_EAGAIN(err)) return 0; else { get_socket_error(); return RKTIO_READ_ERROR; } } }
int check_socket_event(int fd,int seconds,bool read_event,bool write_event) { struct pollfd pfd = {0} ; pfd.fd = fd; pfd.events = 0 ; if(read_event) pfd.events |= POLLIN ; if(write_event) pfd.events |= POLLOUT ; if( poll(&pfd,1,seconds*1000) <1) { errno = ETIMEDOUT ; return -1 ; } errno = get_socket_error(fd) ; if ( errno!=0 ) { return -1 ; } return 0 ; }
void ensure_or_throw_impl(bool condition, const char *errname, const char *funname, const char *file, int line, const char *cond) { if (!condition) { std::stringstream msg; msg << errname << " in " << funname << "() at " << file << ":" << line << ": condition " << cond << " failed: " << get_socket_error(); throw T(msg.str()); } }
int s_poll_canwrite(s_poll_set *fds, SOCKET fd) { /* ignore exception if there is no error (WinCE 6.0 anomaly) */ return FD_ISSET(fd, fds->owfds) || (FD_ISSET(fd, fds->oxfds) && get_socket_error(fd)); }
/****************************** transfer data */ static void transfer(CLI *c) { int watchdog=0; /* a counter to detect an infinite loop */ int num, err; /* logical channels (not file descriptors!) open for read or write */ int sock_open_rd=1, sock_open_wr=1, ssl_open_rd=1, ssl_open_wr=1; /* awaited conditions on SSL file descriptors */ int shutdown_wants_read=0, shutdown_wants_write=0; int read_wants_read, read_wants_write=0; int write_wants_read=0, write_wants_write; /* actual conditions on file descriptors */ int sock_can_rd, sock_can_wr, ssl_can_rd, ssl_can_wr; c->sock_ptr=c->ssl_ptr=0; do { /* main loop of client data transfer */ /****************************** initialize *_wants_* */ read_wants_read= ssl_open_rd && c->ssl_ptr<BUFFSIZE && !read_wants_write; write_wants_write= ssl_open_wr && c->sock_ptr && !write_wants_read; /****************************** setup c->fds structure */ s_poll_init(&c->fds); /* initialize the structure */ /* for plain socket open data strem = open file descriptor */ /* make sure to add each open socket to receive exceptions! */ if(sock_open_rd) s_poll_add(&c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0); if(sock_open_wr) s_poll_add(&c->fds, c->sock_wfd->fd, 0, c->ssl_ptr); /* for SSL assume that sockets are open if there any pending requests */ if(read_wants_read || write_wants_read || shutdown_wants_read) s_poll_add(&c->fds, c->ssl_rfd->fd, 1, 0); if(read_wants_write || write_wants_write || shutdown_wants_write) s_poll_add(&c->fds, c->ssl_wfd->fd, 0, 1); /****************************** wait for an event */ err=s_poll_wait(&c->fds, (sock_open_rd && ssl_open_rd) /* both peers open */ || c->ssl_ptr /* data buffered to write to socket */ || c->sock_ptr /* data buffered to write to SSL */ ? c->opt->timeout_idle : c->opt->timeout_close, 0); switch(err) { case -1: sockerror("transfer: s_poll_wait"); longjmp(c->err, 1); case 0: /* timeout */ if((sock_open_rd && ssl_open_rd) || c->ssl_ptr || c->sock_ptr) { s_log(LOG_INFO, "transfer: s_poll_wait:" " TIMEOUTidle exceeded: sending reset"); longjmp(c->err, 1); } else { /* already closing connection */ s_log(LOG_ERR, "transfer: s_poll_wait:" " TIMEOUTclose exceeded: closing"); return; /* OK */ } } /****************************** check for errors on sockets */ err=s_poll_error(&c->fds, c->sock_rfd->fd); if(err) { s_log(LOG_NOTICE, "Error detected on socket (read) file descriptor: %s (%d)", s_strerror(err), err); longjmp(c->err, 1); } if(c->sock_wfd->fd != c->sock_rfd->fd) { /* performance optimization */ err=s_poll_error(&c->fds, c->sock_wfd->fd); if(err) { s_log(LOG_NOTICE, "Error detected on socket write file descriptor: %s (%d)", s_strerror(err), err); longjmp(c->err, 1); } } err=s_poll_error(&c->fds, c->ssl_rfd->fd); if(err) { s_log(LOG_NOTICE, "Error detected on SSL (read) file descriptor: %s (%d)", s_strerror(err), err); longjmp(c->err, 1); } if(c->ssl_wfd->fd != c->ssl_rfd->fd) { /* performance optimization */ err=s_poll_error(&c->fds, c->ssl_wfd->fd); if(err) { s_log(LOG_NOTICE, "Error detected on SSL write file descriptor: %s (%d)", s_strerror(err), err); longjmp(c->err, 1); } } /****************************** retrieve results from c->fds */ sock_can_rd=s_poll_canread(&c->fds, c->sock_rfd->fd); sock_can_wr=s_poll_canwrite(&c->fds, c->sock_wfd->fd); ssl_can_rd=s_poll_canread(&c->fds, c->ssl_rfd->fd); ssl_can_wr=s_poll_canwrite(&c->fds, c->ssl_wfd->fd); /****************************** checks for internal failures */ /* please report any internal errors to stunnel-users mailing list */ if(!(sock_can_rd || sock_can_wr || ssl_can_rd || ssl_can_wr)) { s_log(LOG_ERR, "INTERNAL ERROR: " "s_poll_wait returned %d, but no descriptor is ready", err); longjmp(c->err, 1); } /* these checks should no longer be needed */ /* I'm going to remove them soon */ if(!sock_open_rd && sock_can_rd) { err=get_socket_error(c->sock_rfd->fd); if(err) { /* really an error? */ s_log(LOG_ERR, "INTERNAL ERROR: " "Closed socket ready to read: %s (%d)", s_strerror(err), err); longjmp(c->err, 1); } if(c->ssl_ptr) { /* anything left to write */ s_log(LOG_ERR, "INTERNAL ERROR: " "Closed socket ready to read: sending reset"); longjmp(c->err, 1); } s_log(LOG_ERR, "INTERNAL ERROR: " "Closed socket ready to read: write close"); sock_open_wr=0; /* no further write allowed */ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ } /****************************** send SSL close_notify message */ if(shutdown_wants_read || shutdown_wants_write) { shutdown_wants_read=shutdown_wants_write=0; num=SSL_shutdown(c->ssl); /* send close_notify */ if(num<0) /* -1 - not completed */ err=SSL_get_error(c->ssl, num); else /* 0 or 1 - success */ err=SSL_ERROR_NONE; switch(err) { case SSL_ERROR_NONE: /* the shutdown was successfully completed */ s_log(LOG_INFO, "SSL_shutdown successfully sent close_notify"); break; case SSL_ERROR_WANT_WRITE: s_log(LOG_DEBUG, "SSL_shutdown returned WANT_WRITE: retrying"); shutdown_wants_write=1; break; case SSL_ERROR_WANT_READ: s_log(LOG_DEBUG, "SSL_shutdown returned WANT_READ: retrying"); shutdown_wants_read=1; break; case SSL_ERROR_SYSCALL: /* socket error */ parse_socket_error(c, "SSL_shutdown"); break; case SSL_ERROR_SSL: /* SSL error */ sslerror("SSL_shutdown"); longjmp(c->err, 1); default: s_log(LOG_ERR, "SSL_shutdown/SSL_get_error returned %d", err); longjmp(c->err, 1); } } /****************************** read from socket */ if(sock_open_rd && sock_can_rd) { num=readsocket(c->sock_rfd->fd, c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr); switch(num) { case -1: parse_socket_error(c, "readsocket"); break; case 0: /* close */ s_log(LOG_DEBUG, "Socket closed on read"); sock_open_rd=0; break; default: c->sock_ptr+=num; watchdog=0; /* reset watchdog */ } } /****************************** write to socket */ if(sock_open_wr && sock_can_wr) { num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr); switch(num) { case -1: /* error */ parse_socket_error(c, "writesocket"); break; case 0: s_log(LOG_DEBUG, "No data written to the socket: retrying"); break; default: memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num); c->ssl_ptr-=num; c->sock_bytes+=num; watchdog=0; /* reset watchdog */ } } /****************************** update *_wants_* based on new *_ptr */ /* this update is also required for SSL_pending() to be used */ read_wants_read= ssl_open_rd && c->ssl_ptr<BUFFSIZE && !read_wants_write; write_wants_write= ssl_open_wr && c->sock_ptr && !write_wants_read; /****************************** read from SSL */ if((read_wants_read && (ssl_can_rd || SSL_pending(c->ssl))) || /* it may be possible to read some pending data after * writesocket() above made some room in c->ssl_buff */ (read_wants_write && ssl_can_wr)) { read_wants_write=0; num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr); switch(err=SSL_get_error(c->ssl, num)) { case SSL_ERROR_NONE: c->ssl_ptr+=num; watchdog=0; /* reset watchdog */ break; case SSL_ERROR_WANT_WRITE: s_log(LOG_DEBUG, "SSL_read returned WANT_WRITE: retrying"); read_wants_write=1; break; case SSL_ERROR_WANT_READ: /* nothing unexpected */ break; case SSL_ERROR_WANT_X509_LOOKUP: s_log(LOG_DEBUG, "SSL_read returned WANT_X509_LOOKUP: retrying"); break; case SSL_ERROR_SYSCALL: if(!num) { /* EOF */ if(c->sock_ptr) { s_log(LOG_ERR, "SSL socket closed on SSL_read " "with %d byte(s) in buffer", c->sock_ptr); longjmp(c->err, 1); /* reset the socket */ } s_log(LOG_DEBUG, "SSL socket closed on SSL_read"); ssl_open_rd=ssl_open_wr=0; /* buggy peer: no close_notify */ } else parse_socket_error(c, "SSL_read"); break; case SSL_ERROR_ZERO_RETURN: /* close_notify received */ s_log(LOG_DEBUG, "SSL closed on SSL_read"); ssl_open_rd=0; if(!strcmp(SSL_get_version(c->ssl), "SSLv2")) ssl_open_wr=0; break; case SSL_ERROR_SSL: sslerror("SSL_read"); longjmp(c->err, 1); default: s_log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err); longjmp(c->err, 1); } } /****************************** write to SSL */ if((write_wants_read && ssl_can_rd) || (write_wants_write && ssl_can_wr)) { write_wants_read=0; num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr); switch(err=SSL_get_error(c->ssl, num)) { case SSL_ERROR_NONE: memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num); c->sock_ptr-=num; c->ssl_bytes+=num; watchdog=0; /* reset watchdog */ break; case SSL_ERROR_WANT_WRITE: /* nothing unexpected */ break; case SSL_ERROR_WANT_READ: s_log(LOG_DEBUG, "SSL_write returned WANT_READ: retrying"); write_wants_read=1; break; case SSL_ERROR_WANT_X509_LOOKUP: s_log(LOG_DEBUG, "SSL_write returned WANT_X509_LOOKUP: retrying"); break; case SSL_ERROR_SYSCALL: /* socket error */ if(!num) { /* EOF */ if(c->sock_ptr) { s_log(LOG_ERR, "SSL socket closed on SSL_write " "with %d byte(s) in buffer", c->sock_ptr); longjmp(c->err, 1); /* reset the socket */ } s_log(LOG_DEBUG, "SSL socket closed on SSL_write"); ssl_open_rd=ssl_open_wr=0; /* buggy peer: no close_notify */ } else parse_socket_error(c, "SSL_write"); break; case SSL_ERROR_ZERO_RETURN: /* close_notify received */ s_log(LOG_DEBUG, "SSL closed on SSL_write"); ssl_open_rd=0; if(!strcmp(SSL_get_version(c->ssl), "SSLv2")) ssl_open_wr=0; break; case SSL_ERROR_SSL: sslerror("SSL_write"); longjmp(c->err, 1); default: s_log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err); longjmp(c->err, 1); } } /****************************** check write shutdown conditions */ if(sock_open_wr && !ssl_open_rd && !c->ssl_ptr) { s_log(LOG_DEBUG, "Sending socket write shutdown"); sock_open_wr=0; /* no further write allowed */ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ } if(ssl_open_wr && !sock_open_rd && !c->sock_ptr) { s_log(LOG_DEBUG, "Sending SSL write shutdown"); ssl_open_wr=0; /* no further write allowed */ if(strcmp(SSL_get_version(c->ssl), "SSLv2")) { /* SSLv3, TLSv1 */ shutdown_wants_write=1; /* initiate close_notify */ } else { /* no alerts in SSLv2 including close_notify alert */ shutdown(c->sock_rfd->fd, SHUT_RD); /* notify the kernel */ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ SSL_set_shutdown(c->ssl, /* notify the OpenSSL library */ SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); ssl_open_rd=0; /* no further read allowed */ } } /****************************** check watchdog */ if(++watchdog>100) { /* loop executes without transferring any data */ s_log(LOG_ERR, "transfer() loop executes not transferring any data"); s_log(LOG_ERR, "please report the problem to [email protected]"); stunnel_info(LOG_ERR); s_log(LOG_ERR, "protocol=%s, SSL_pending=%d", SSL_get_version(c->ssl), SSL_pending(c->ssl)); s_log(LOG_ERR, "sock_open_rd=%s, sock_open_wr=%s, " "ssl_open_rd=%s, ssl_open_wr=%s", sock_open_rd ? "Y" : "n", sock_open_wr ? "Y" : "n", ssl_open_rd ? "Y" : "n", ssl_open_wr ? "Y" : "n"); s_log(LOG_ERR, "sock_can_rd=%s, sock_can_wr=%s, " "ssl_can_rd=%s, ssl_can_wr=%s", sock_can_rd ? "Y" : "n", sock_can_wr ? "Y" : "n", ssl_can_rd ? "Y" : "n", ssl_can_wr ? "Y" : "n"); s_log(LOG_ERR, "read_wants_read=%s, read_wants_write=%s", read_wants_read ? "Y" : "n", read_wants_write ? "Y" : "n"); s_log(LOG_ERR, "write_wants_read=%s, write_wants_write=%s", write_wants_read ? "Y" : "n", write_wants_write ? "Y" : "n"); s_log(LOG_ERR, "shutdown_wants_read=%s, shutdown_wants_write=%s", shutdown_wants_read ? "Y" : "n", shutdown_wants_write ? "Y" : "n"); s_log(LOG_ERR, "socket input buffer: %d byte(s), " "ssl input buffer: %d byte(s)", c->sock_ptr, c->ssl_ptr); longjmp(c->err, 1); } } while(sock_open_wr || ssl_open_wr || shutdown_wants_read || shutdown_wants_write); }
static int handle_connection(HTTPContext *c) { int len, ret; switch(c->state) { case HTTPSTATE_WAIT_REQUEST: /* timeout ? */ if ((c->timeout - cur_time) < 0) return -1; if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLIN)) return 0; /* read the data */ read_loop: len = recv(c->fd, c->buffer_ptr, 1, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) return -1; } else if (len == 0) { if(!c->keep_alive)return -1; } else { /* search for end of request. */ uint8_t *ptr; c->buffer_ptr += len; ptr = c->buffer_ptr; if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { /* request found : parse it and reply */ ret = http_parse_request(c); if (ret < 0) return -1; } else if (ptr >= c->buffer_end) { /* request too long: cannot do anything */ return -1; } else goto read_loop; } break; case HTTPSTATE_SEND_HEADER: if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { goto close_conn; } } else { c->buffer_ptr += len; c->data_count += len; if (c->buffer_ptr >= c->buffer_end) { av_freep(&c->pb_buffer); if(c->keep_alive){ memset(c->buffer, 0, c->buffer_size); c->buffer_ptr = c->buffer; c->buffer_end = c->buffer + c->buffer_size - 1; c->timeout = cur_time + HTTP_REQUEST_TIMEOUT; c->state = HTTPSTATE_WAIT_REQUEST; c->hls_idx = -1; http_log("%u alive %s\n", ntohs(c->from_addr.sin_port), c->url); return 0; } /* if error, exit */ if (c->http_error) return -1; /* all the buffer was sent : synchronize to the incoming*/ c->state = HTTPSTATE_SEND_DATA_HEADER; c->buffer_ptr = c->buffer_end = c->buffer; } } break; case HTTPSTATE_SEND_DATA: case HTTPSTATE_SEND_DATA_HEADER: case HTTPSTATE_SEND_DATA_TRAILER: if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; if (http_send_data(c) < 0) return -1; /* close connection if trailer sent */ if (c->state == HTTPSTATE_SEND_DATA_TRAILER) return -1; break; case HTTPSTATE_RECEIVE_DATA: /* no need to read if no events */ if (c->poll_entry->revents & (POLLERR | POLLHUP)){ HLS *s = NULL; if(c->hls_idx >= 0){ s = &s_hls[c->hls_idx]; s->flag = 2; } wake_others(c, HTTPSTATE_SEND_DATA_TRAILER); return -1; } if (!(c->poll_entry->revents & POLLIN)) return 0; if (http_receive_data(c) < 0) return -1; break; case HTTPSTATE_WAIT_FEED: /* no need to read if no events */ if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP)) /*19*/ {printf("line %d: %x:%d\n", __LINE__, c->poll_entry->revents, get_socket_error(c->fd)); return -1;} /* nothing to do, we'll be waken up by incoming feed packets */ break; default: return -1; } return 0; close_conn: av_freep(&c->pb_buffer); return -1; }