static void socketDoEvent(WebsSocket *sp) { int sid; assert(sp); sid = sp->sid; if (sp->currentEvents & SOCKET_READABLE) { if (sp->flags & SOCKET_LISTENING) { socketAccept(sp); sp->currentEvents = 0; return; } } /* Now invoke the users socket handler. NOTE: the handler may delete the socket, so we must be very careful after calling the handler. */ if (sp->handler && (sp->handlerMask & sp->currentEvents)) { (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data); /* Make sure socket pointer is still valid, then reset the currentEvents. */ if (socketList && sid < socketMax && socketList[sid] == sp) { sp->currentEvents = 0; } } }
int socketCreatePair(int* fd1, int* fd2) { #ifndef _WIN32 int fds[2]; int ret = ::socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (!ret) { socketSetNonBlocking(fds[0]); socketSetNonBlocking(fds[1]); *fd1 = fds[0]; *fd2 = fds[1]; } else { DPLOG(ERROR) << "Could not create socket pair\n"; } return ret; #else /* _WIN32 */ /* on Windows, select() only works with network sockets, which * means we absolutely cannot use Win32 PIPEs to implement * socket pairs with the current event loop implementation. * We're going to do like Cygwin: create a random pair * of localhost TCP sockets and connect them together */ /* first, create the 'server' socket. * a port number of 0 means 'any port between 1024 and 5000. * see Winsock bind() documentation for details */ ScopedSocket s0(socketTcpLoopbackServer(0)); if (s0.get() < 0) { return -1; } // IMPORTANT: Keep the s0 socket in blocking mode, or the accept() // below may fail with WSAEWOULDBLOCK randomly. /* now connect a client socket to it, we first need to * extract the server socket's port number */ int port = socketGetPort(s0.get()); ScopedSocket s2(socketTcpLoopbackClient(port)); if (!s2.valid()) { return -1; } /* we need to accept the connection on the server socket * this will create the second socket for the pair */ ScopedSocket s1(socketAccept(s0.get())); if (!s1.valid()) { DPLOG(ERROR) << "Could not accept connection from server socket\n"; return -1; } socketSetNonBlocking(s1.get()); *fd1 = s1.release(); *fd2 = s2.release(); return 0; #endif /* _WIN32 */ }
static int socketDoEvent(socket_t *sp) { ringq_t *rq; int sid; a_assert(sp); sid = sp->sid; if (sp->currentEvents & SOCKET_READABLE) { if (sp->flags & SOCKET_LISTENING) { socketAccept(sp); sp->currentEvents = 0; return 1; } } else { /* * If there is still read data in the buffers, trigger the read handler * NOTE: this may busy spin if the read handler doesn't read the data */ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { sp->currentEvents |= SOCKET_READABLE; } } /* * If now writable and flushing in the background, continue flushing */ if (sp->currentEvents & SOCKET_WRITABLE) { if (sp->flags & SOCKET_FLUSHING) { rq = &sp->outBuf; if (ringqLen(rq) > 0) { socketFlush(sp->sid); } else { sp->flags &= ~SOCKET_FLUSHING; } } } /* * Now invoke the users socket handler. NOTE: the handler may delete the * socket, so we must be very careful after calling the handler. */ if (sp->handler && (sp->handlerMask & sp->currentEvents)) { (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data); /* * Make sure socket pointer is still valid, then reset the currentEvents. */ if (socketList && sid < socketMax && socketList[sid] == sp) { sp->currentEvents = 0; } } return 1; }
static void scanSockets(void) { uint16 i; for (i = 0; i < SOAD_SOCKET_COUNT; i++) { // pi_printf("infor: scan sockets "); mini_uart_sendDec(i); pi_printf(" \r\n"); switch (SocketAdminList[i].SocketState) { case SOCKET_INIT: socketCreate(i); // pi_printf("infor: socket create"); mini_uart_sendDec(i); pi_printf(" \r\n"); break; case SOCKET_TCP_LISTENING: socketAccept(i); // pi_printf("infor: socket accept"); mini_uart_sendDec(i); pi_printf(" \r\n"); break; case SOCKET_TCP_READY: // pi_printf("infor: socket read "); mini_uart_sendDec(i); pi_printf(" \r\n"); socketTcpRead(i); break; case SOCKET_UDP_READY: socketUdpRead(i); break; case SOCKET_DUPLICATE: /* Do nothing */ break; default: /* This should never happen! */ DET_REPORTERROR(MODULE_ID_SOAD, 0, SOAD_SCAN_SOCKETS_ID, SOAD_E_SHALL_NOT_HAPPEN); break; } /* End of switch */ } /* End of for */ }
void CSocketServer::runSocketAccept() { int nChildSocketFD = -1; while (1) { nChildSocketFD = socketAccept(); if (-1 != nChildSocketFD) { sendMessage(m_nInternalFilter, EVENT_COMMAND_SOCKET_ACCEPT, nChildSocketFD, 0, NULL); } else { _DBG("socket server accept fail"); sleep(3); } } sendMessage(m_nInternalFilter, EVENT_COMMAND_THREAD_EXIT, threadHandler->getThreadID(), 0, NULL); threadHandler->threadExit(); }
void CHttpServer::runSocketAccept() { int nChildSocketFD = -1; while (1) { nChildSocketFD = socketAccept(); if (-1 != nChildSocketFD) { sendMessage(EVENT_FILTER_HTTP_SERVER, EVENT_COMMAND_SOCKET_ACCEPT, nChildSocketFD, 0, NULL); } else { _DBG("socket server accept fail"); } } sendMessage(EVENT_FILTER_HTTP_SERVER, EVENT_COMMAND_THREAD_EXIT, threadHandler->getThreadID(), 0, NULL); threadHandler->threadExit(); }
void tcpEchoListenerTask(void *param) { error_t error; uint16_t clientPort; IpAddr clientIpAddr; Socket *serverSocket; Socket *clientSocket; EchoServiceContext *context; OsTask *task; //Point to the listening socket serverSocket = (Socket *) param; //Main loop while(1) { //Accept an incoming connection clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort); //Check whether a valid connection request has been received if(!clientSocket) continue; //Debug message TRACE_INFO("Echo service: connection established with client %s port %u\r\n", ipAddrToString(&clientIpAddr, NULL), clientPort); //The socket operates in non-blocking mode error = socketSetTimeout(clientSocket, 0); //Any error to report? if(error) { //Close socket socketClose(clientSocket); //Wait for an incoming connection attempt continue; } //Allocate resources for the new connection context = osMemAlloc(sizeof(EchoServiceContext)); //Failed to allocate memory? if(!context) { //Close socket socketClose(clientSocket); //Wait for an incoming connection attempt continue; } //Record the handle of the newly created socket context->socket = clientSocket; //Create a task to service the current connection task = osTaskCreate("TCP Echo Connection", tcpEchoConnectionTask, context, ECHO_SERVICE_STACK_SIZE, ECHO_SERVICE_PRIORITY); //Did we encounter an error? if(task == OS_INVALID_HANDLE) { //Close socket socketClose(clientSocket); //Release resources osMemFree(context); } } }
int_t accept(int_t s, sockaddr *addr, int_t *addrlen) { uint16_t port; IpAddr ipAddr; Socket *socket; Socket *newSocket; //Make sure the socket descriptor is valid if(s < 0 || s >= SOCKET_MAX_COUNT) { socketError(NULL, ERROR_INVALID_SOCKET); return SOCKET_ERROR; } //Point to the socket structure socket = &socketTable[s]; //Permit an incoming connection attempt on a socket newSocket = socketAccept(socket, &ipAddr, &port); //The address is optional if(addr != NULL && addrlen != NULL) { #if (IPV4_SUPPORT == ENABLED) //IPv4 address? if(ipAddr.length == sizeof(Ipv4Addr) && *addrlen >= sizeof(sockaddr_in)) { //Point to the IPv4 address information sockaddr_in *sa = (sockaddr_in *) addr; //Set address family and port number sa->sin_family = AF_INET; sa->sin_port = htons(port); //Copy IPv4 address sa->sin_addr.s_addr = ipAddr.ipv4Addr; //Return the actual length of the address *addrlen = sizeof(sockaddr_in); } else #endif #if (IPV6_SUPPORT == ENABLED) //IPv6 address? if(ipAddr.length == sizeof(Ipv6Addr) && *addrlen >= sizeof(sockaddr_in6)) { //Point to the IPv6 address information sockaddr_in6 *sa = (sockaddr_in6 *) addr; //Set address family and port number sa->sin6_family = AF_INET6; sa->sin6_port = htons(port); //Copy IPv6 address ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr); //Return the actual length of the address *addrlen = sizeof(sockaddr_in6); } else #endif //Invalid address? { //Close socket socketClose(newSocket); //Report an error socketError(socket, ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } } //Return the descriptor to the new socket return newSocket->descriptor; }
int main(int argc, char **argv) #endif { sslConn_t *cp; sslKeys_t *keys; SOCKET listenfd, fd; WSADATA wsaData; unsigned char buf[1024]; unsigned char *response, *c; int responseHdrLen, acceptAgain, flags; int bytes, status, quit, again, rc, err; #if USE_MEM_CERTS unsigned char *servBin, *servKeyBin, *caBin; int servBinLen, caBinLen, servKeyBinLen; #endif cp = NULL; /* Initialize Windows sockets (no-op on other platforms) */ WSAStartup(MAKEWORD(1,1), &wsaData); /* Initialize the MatrixSSL Library, and read in the public key (certificate) and private key. */ if (matrixSslOpen() < 0) { fprintf(stderr, "matrixSslOpen failed, exiting..."); } #if USE_MEM_CERTS /* Example of DER binary certs for matrixSslReadKeysMem */ getFileBin("certSrv.der", &servBin, &servBinLen); getFileBin("privkeySrv.der", &servKeyBin, &servKeyBinLen); getFileBin("CACertCln.der", &caBin, &caBinLen); matrixSslReadKeysMem(&keys, servBin, servBinLen, servKeyBin, servKeyBinLen, caBin, caBinLen); free(servBin); free(servKeyBin); free(caBin); #else /* Standard PEM files */ if (matrixSslReadKeys(&keys, certfile, keyfile, NULL, NULL) < 0) { fprintf(stderr, "Error reading or parsing %s or %s.\n", certfile, keyfile); goto promptAndExit; } #endif /* USE_MEM_CERTS */ fprintf(stdout, "Run httpsClient or type https://127.0.0.1:%d into your local Web browser.\n", HTTPS_PORT); /* Create the listen socket */ if ((listenfd = socketListen(HTTPS_PORT, &err)) == INVALID_SOCKET) { fprintf(stderr, "Cannot listen on port %d\n", HTTPS_PORT); goto promptAndExit; } /* Set blocking or not on the listen socket */ setSocketBlock(listenfd); /* Loop control initalization */ quit = 0; again = 0; flags = 0; acceptAgain = 1; /* Main connection loop */ while (!quit) { if (acceptAgain) { /* sslAccept creates a new server session */ /* TODO - deadlock on blocking socket accept. Should disable blocking here */ if ((fd = socketAccept(listenfd, &err)) == INVALID_SOCKET) { fprintf(stdout, "Error accepting connection: %d\n", err); continue; } if ((rc = sslAccept(&cp, fd, keys, NULL, flags)) != 0) { socketShutdown(fd); continue; } flags = 0; acceptAgain = 0; } /* Read response < 0 return indicates an error. 0 return indicates an EOF or CLOSE_NOTIFY in this situation > 0 indicates that some bytes were read. Keep reading until we see the /r/n/r/n from the GET request. We don't actually parse the request, we just echo it back. */ c = buf; readMore: if ((rc = sslRead(cp, c, sizeof(buf) - (int)(c - buf), &status)) > 0) { c += rc; if (c - buf < 4 || memcmp(c - 4, "\r\n\r\n", 4) != 0) { goto readMore; } } else { if (rc < 0) { fprintf(stdout, "sslRead error. dropping connection.\n"); } if (rc < 0 || status == SSLSOCKET_EOF || status == SSLSOCKET_CLOSE_NOTIFY) { socketShutdown(cp->fd); sslFreeConnection(&cp); acceptAgain = 1; continue; } goto readMore; } /* Done reading. If the incoming data starts with the quitString, quit the application after this request */ if (memcmp(buf, quitString, min(c - buf, (int)strlen(quitString))) == 0) { quit++; fprintf(stdout, "Q"); } /* If the incoming data starts with the againString, we are getting a pipeline request on the same session. Don't close and wait for new connection in this case. */ if (memcmp(buf, againString, min(c - buf, (int)strlen(againString))) == 0) { again++; fprintf(stdout, "A"); } else { fprintf(stdout, "R"); again = 0; } /* Copy the canned response header and decoded data from socket as the response (reflector) */ responseHdrLen = (int)strlen(responseHdr); bytes = responseHdrLen + (int)(c - buf); response = malloc(bytes); memcpy(response, responseHdr, responseHdrLen); memcpy(response + responseHdrLen, buf, c - buf); /* Send response. < 0 return indicates an error. 0 return indicates not all data was sent and we must retry > 0 indicates that all requested bytes were sent */ writeMore: rc = sslWrite(cp, response, bytes, &status); if (rc < 0) { free(response); fprintf(stdout, "Internal sslWrite error\n"); socketShutdown(cp->fd); sslFreeConnection(&cp); continue; } else if (rc == 0) { goto writeMore; } free(response); /* If we saw an /again request, loop up and process another pipelined HTTP request. The /again request is supported in the httpsClient example code. */ if (again) { continue; } /* Send a closure alert for clean shutdown of remote SSL connection This is for good form, some implementations just close the socket */ sslWriteClosureAlert(cp); /* Close the socket and wait for next connection (new session) */ socketShutdown(cp->fd); sslFreeConnection(&cp); acceptAgain = 1; } /* Close listening socket, free remaining items */ if (cp && cp->ssl) { socketShutdown(cp->fd); sslFreeConnection(&cp); } socketShutdown(listenfd); matrixSslFreeKeys(keys); matrixSslClose(); WSACleanup(); promptAndExit: fprintf(stdout, "\n\nPress return to exit...\n"); getchar(); return 0; }
API bool connectClientSocketAsync(Socket *s, int timeout) { if(s->connected) { logError("Cannot connect already connected socket %d", s->fd); return false; } if(s->type != SOCKET_CLIENT) { logError("Cannot asynchronously connect non-client socket"); return false; } struct addrinfo hints; struct addrinfo *server; int ret; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; // don't care if we use IPv4 or IPv6 to reach our destination hints.ai_socktype = SOCK_STREAM; // TCP stream sockets if((ret = getaddrinfo(s->host, s->port, &hints, &server)) != 0) { logError("Failed to look up address %s:%s: %s", s->host, s->port, gai_strerror(ret)); return false; } if((s->fd = socket(server->ai_family, server->ai_socktype, server->ai_protocol)) == -1) { logSystemError("Failed to create socket"); return false; } if(!setSocketNonBlocking(s->fd)) { logSystemError("Failed to set socket non-blocking"); closeSocket(s); return false; } logNotice("Asynchronously connecting client socket %d to %s:%s...", s->fd, s->host, s->port); if(connect(s->fd, server->ai_addr, server->ai_addrlen) < 0) { // try to connect socket #ifdef WIN32 if(WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK) { #else if(errno == EINPROGRESS) { #endif // free previous timer if present free(s->custom); AsyncConnectionTimer *timer = ALLOCATE_OBJECT(AsyncConnectionTimer); timer->creationTime = getMicroTime(); timer->timeout = timeout; s->custom = timer; g_queue_push_tail(connecting, s); // add to connecting list logInfo("Socket %d delayed connection, queueing...", s->fd); } else { #ifdef WIN32 char *error = g_win32_error_message(WSAGetLastError()); logError("Connection for socket %d failed: %s", s->fd, error); free(error); #else logSystemError("Connection for socket %d failed", s->fd); #endif closeSocket(s); freeaddrinfo(server); return false; } } else { logNotice("Direct response for asynchronous connection on socket %d", s->fd); s->connected = true; triggerEvent(s, "connected"); enableSocketPolling(s); } freeaddrinfo(server); return true; } API bool enableSocketPolling(Socket *socket) { if(isSocketPollingEnabled(socket)) { // Socket with that fd is already polled return false; } int *fd = ALLOCATE_OBJECT(int); *fd = socket->fd; g_hash_table_insert(poll_table, fd, socket); return true; } API bool isSocketPollingEnabled(Socket *socket) { return g_hash_table_lookup(poll_table, &socket->fd) != NULL; } API bool disableSocketPolling(Socket *socket) { return g_hash_table_remove(poll_table, &socket->fd) == true; } API void pollSockets() { if(!polling) { polling = true; // set polling flag to lock our poll table in order to make this function reentrancy safe if(!g_queue_is_empty(connecting)) { GQueue *connectingSockets = g_queue_copy(connecting); // copy the connecting socket list so we may modify the list while polling for(GList *iter = connectingSockets->head; iter != NULL; iter = iter->next) { if(pollConnectingSocket(iter->data)) { // poll the connecting socket // The socket should no longer be polled g_queue_remove(connecting, iter->data); // remove it from the original connecting queue } } g_queue_free(connectingSockets); // remove our temporary iteration list } GList *sockets = g_hash_table_get_values(poll_table); // get a static list of sockets so we may modify the hash table while polling for(GList *iter = sockets; iter != NULL; iter = iter->next) { Socket *poll = iter->data; int fd; // storage for the file descriptor that won't be available anymore in case the socket gets freed before we remove it if(pollSocket(poll, &fd)) { // poll the socket // The socket should no longer be polled g_hash_table_remove(poll_table, &fd); // remove it from the polling table } } g_list_free(sockets); // remove our temporary iteration list polling = false; // release pseudo lock on poll table } } API bool isSocketsPolling() { return polling; } API Socket *getPolledSocketByFd(int fd) { return g_hash_table_lookup(poll_table, &fd); } /** * Callback to poll all sockets signed up for polling */ TIMER_CALLBACK(poll) { pollSockets(); triggerEvent(NULL, "sockets_polled"); TIMER_ADD_TIMEOUT(pollInterval, poll); } /** * Polls a connecting socket and notifies the caller of whether it should be removed from the connecting polling queue afterwards * * @param socket the connecting socket to poll * @result true if the socket should be removed from the connecting polling queue after polling */ static bool pollConnectingSocket(Socket *socket) { assert(!socket->connected); assert(socket->type == SOCKET_CLIENT); assert(socket->custom != NULL); // Check whether the socket has timed out yet AsyncConnectionTimer *timer = socket->custom; if(getMicroTime() - timer->creationTime > timer->timeout) { // connection timed out logWarning("Asynchronous connection on socket %d timed out", socket->fd); closeSocket(socket); triggerEvent(socket, "disconnect"); return true; } // Initialize timeout struct timeval tv = {0, 0}; // Initialize write fd set fd_set fdset; FD_ZERO(&fdset); FD_SET(socket->fd, &fdset); // Select socket for write flag (connected) int ret; if((ret = select(socket->fd + 1, NULL, &fdset, NULL, &tv)) < 0) { #ifdef WIN32 if(WSAGetLastError() != WSAEINTR) { char *error = g_win32_error_message(WSAGetLastError()); logError("Error selecting socket %d for write flag (connected) while polling: %s", socket->fd, error); free(error); #else if(errno != EINTR) { logSystemError("Error selecting socket %d for write flag (connected) while polling", socket->fd); #endif closeSocket(socket); triggerEvent(socket, "disconnect"); return true; } // EINTR at this point means the socket is just not connected yet, so we can safely return and continue polling another time return false; } else if(ret > 0) { // there is a write flag on the socket // Socket selected for write, check if we're indeed connected int valopt; socklen_t lon = sizeof(int); if(getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void*) (&valopt), &lon) < 0) { logSystemError("getsockopt() failed on socket %d", socket->fd); closeSocket(socket); triggerEvent(socket, "disconnect"); return true; } else if(valopt != 0) { // There was a connection error logSystemError("Asynchronous connection on socket %d failed", socket->fd); closeSocket(socket); triggerEvent(socket, "disconnect"); return true; } logNotice("Asynchronously connected socket %d", socket->fd); socket->connected = true; triggerEvent(socket, "connected"); enableSocketPolling(socket); return true; } // the socket doesn't have a write flag, so let's just wait until it's connected return false; } /** * Polls a socket and notifies the caller of whether it should be removed from the polling table afterwards * * @param socket the socket to poll * @param fd_p a pointer to an integer field to which the file descriptor of the socket should be written in case the socket should be removed from the polling table and could already be freed at that time * @result true if the socket should be removed from the polling table after polling */ static bool pollSocket(Socket *socket, int *fd_p) { *fd_p = socket->fd; // backup file descriptor if(!socket->connected) { // Socket is disconnected triggerEvent(socket, "disconnect"); return true; } if(socket->type != SOCKET_SERVER && socket->type != SOCKET_SERVER_BLOCK) { int ret; if((ret = socketReadRaw(socket, poll_buffer, SOCKET_POLL_BUFSIZE)) < 0) { if(socket->connected) { // socket is still connected, so the error was not fatal triggerEvent(socket, "error"); return false; } else { // socket was disconnected either by the peer or by a fatal error triggerEvent(socket, "disconnect"); return true; } } else if(ret > 0) { // we actually read something triggerEvent(socket, "read", poll_buffer, ret); } // else nothing to read right now } else { Socket *clientSocket; if((clientSocket = socketAccept(socket)) != NULL) { triggerEvent(socket, "accept", clientSocket); } else { if(socket->connected) { // socket is still connected, so the error was not fatal triggerEvent(socket, "error"); return false; } else { // socket was disconnected either by the peer or by a fatal error triggerEvent(socket, "disconnect"); return true; } } } return false; }
void httpListenerTask(void *param) { uint_t i; uint_t counter; uint16_t clientPort; IpAddr clientIpAddr; HttpServerContext *context; HttpConnection* connection; Socket *socket; //Retrieve the HTTP server context context = (HttpServerContext *) param; //Process incoming connections to the server for(counter = 1; ; counter++) { //Debug message TRACE_INFO("Ready to accept a new connection...\r\n"); //Limit the number of simultaneous connections to the HTTP server osWaitForSemaphore(&context->semaphore, INFINITE_DELAY); //Loop through available client connections for(i = 0; i < context->settings.maxConnections; i++) { //Point to the current connection connection = &context->connections[i]; //Ready to service the client request? if(!connection->running) { //Accept an incoming connection socket = socketAccept(context->socket, &clientIpAddr, &clientPort); //Make sure the socket handle is valid if(socket != NULL) { //Debug message TRACE_INFO("Connection #%u established with client %s port %" PRIu16 "...\r\n", counter, ipAddrToString(&clientIpAddr, NULL), clientPort); //Reference to the HTTP server settings connection->settings = &context->settings; //Reference to the HTTP server context connection->serverContext = context; //Reference to the new socket connection->socket = socket; //Set timeout for blocking functions socketSetTimeout(connection->socket, HTTP_SERVER_TIMEOUT); //The client connection task is now running... connection->running = TRUE; //Service the current connection request osSetEvent(&connection->startEvent); //We are done break; } } } } }
/* The main loop handles all connections and cleanup. * It returns if there are any problems with the listening socket. */ static void main_loop(void) { int optirun_socket_fd; struct clientsocket * first = 0; //pointer to the first socket struct clientsocket * last = 0; //pointer to the last socket struct clientsocket * curr = 0; //current pointer to a socket struct clientsocket * prev = 0; //previous pointer to a socket bb_log(LOG_INFO, "Started main loop\n"); /* Listen for Optirun conections and act accordingly */ while (bb_status.bb_socket != -1) { usleep(100000); //sleep 100ms to prevent 100% CPU time usage /* Accept a connection. */ optirun_socket_fd = socketAccept(&bb_status.bb_socket, SOCK_NOBLOCK); if (optirun_socket_fd >= 0) { bb_log(LOG_DEBUG, "Accepted new connection\n", optirun_socket_fd, bb_status.appcount); /* add to list of sockets */ curr = malloc(sizeof (struct clientsocket)); curr->sock = optirun_socket_fd; curr->inuse = 0; curr->next = 0; if (last == 0) { first = curr; last = curr; } else { last->next = curr; last = curr; } } /* loop through all connections, removing dead ones, receiving/sending data to the rest */ curr = first; prev = 0; while (curr != 0) { if (curr->sock < 0) { //remove from list if (curr->inuse > 0) { bb_status.appcount--; //stop X / card if there is no need to keep it running if ((bb_status.appcount == 0) && (bb_config.stop_on_exit)) { stop_secondary(); } } if (last == curr) { last = prev; } if (prev == 0) { first = curr->next; free(curr); curr = first; } else { prev->next = curr->next; free(curr); curr = prev->next; } } else { //active connection, handle it. handle_socket(curr); prev = curr; curr = curr->next; } } }//socket server loop /* loop through all connections, closing all of them */ curr = first; prev = 0; while (curr != 0) { //close socket if not already closed if (curr->sock >= 0) { socketClose(&curr->sock); } //remove from list if (curr->inuse > 0) { bb_status.appcount--; } if (last == curr) { last = prev; } if (prev == 0) { first = curr->next; free(curr); curr = first; } else { prev->next = curr->next; free(curr); curr = prev->next; } } }
void proxyAccept(int srv_fd, struct proxyConnection *ncp) { SOCKET src_fd, dst_fd; // struct linger linger; int status; int res; struct timeval tv; int pc, sc; int ccount=0; ILOG("Accepting new connection."); if ((src_fd = socketAccept(srv_fd, &status)) == INVALID_SOCKET) { WLOG("Error accepting connection: %d", status); return; } #ifdef USE_FORK // fork here fd_set rs, ws, es; int fdmax; int pid=fork(); switch(pid) { case -1: /* error */ closesocket(ncp->plain); closesocket(ncp->secure->fd); break; case 0: /* child */ #endif ncp->inuse=1; if (!isClient) { DLOG("Trying to accept ssl connection"); if (sslAccept(&ncp->secure, src_fd, keys, cervalidator, 0)) { WLOG("Error could not establish ssl connection"); socketShutdown(src_fd); /* Gemtek add +++ */ #ifdef USE_FORK quit=1; #endif /* Gemtek add --- */ return; } } setSocketNonblock(src_fd); /* linger.l_onoff = 1; linger.l_linger = 1; setsockopt(src_fd, SOL_SOCKET, SO_LINGER, (char *) &linger,sizeof(linger)); */ /* try to connect to remote end of tunnel */ DLOG("Trying to connect server %s:%d", dst_host, dst_port); if ((dst_fd = socketConnect(dst_host, dst_port, &status)) == INVALID_SOCKET) { WLOG("Error connecting to server %s:%d", dst_host, dst_port); socketShutdown(src_fd); /* Gemtek add +++ */ #ifdef USE_FORK quit=1; #endif /* Gemtek add --- */ return; } if (isClient) { DLOG("Trying to establish an ssl connection to server %s:%d", dst_host, dst_port); if ((sslConnect(&ncp->secure, dst_fd, keys, ncp->sessionId, ncp->cipherSuite, cervalidator)) == INVALID_SOCKET) { WLOG("Error connecting to ssl server %s:%d", dst_host, dst_port); socketShutdown(src_fd); return; } } setSocketNonblock(dst_fd); /* linger.l_onoff = 1; linger.l_linger = 1; setsockopt(dst_fd, SOL_SOCKET, SO_LINGER, (char *) &linger,sizeof(linger)); */ ncp->plain = isClient ? src_fd : dst_fd; ncp->plain_up=1; ncp->secure_up=1; ILOG("Connection established. plain_fd:%d secure_fd:%d", ncp->plain, ncp->secure->fd); // handle remaining bytes in buffer. /* res=proxyReadwrite(ncp,1); if(res<0) { ncp->error=1; closeProxyConnection(ncp); } */ // fork here #ifdef USE_FORK closesocket(srv_fd); fdmax=ncp->plain > ncp->secure->fd ? ncp->plain : ncp->secure->fd; while (!quit) { FD_ZERO(&rs); FD_ZERO(&ws); FD_ZERO(&es); FD_SET(ncp->plain,&rs); FD_SET(ncp->plain,&ws); FD_SET(ncp->plain,&es); FD_SET(ncp->secure->fd,&rs); FD_SET(ncp->secure->fd,&ws); FD_SET(ncp->secure->fd,&es); tv.tv_sec=10; tv.tv_usec=0; DLOG("select on %d open connections. fdmax: %d", ccount, fdmax); res=select(fdmax+1,&rs,NULL,&es,&tv); // DLOG("select returned: %d", res); DLOG("proxyAccept->select returned: %d %s errno=%d", res , strerror(errno), errno ); if(res<0) { perror("select"); continue; } /* if(res==0) continue; */ if(FD_ISSET(ncp->secure->fd,&es) || FD_ISSET(ncp->plain,&es)) { ncp->error=1; break; } sc=proxyReadwrite(ncp,1); if(sc<0) break; pc=proxyReadwrite(ncp,0); if(pc<0) break; if(ncp->done) { quit=1; break; } } closeProxyConnection(ncp); DLOG("done. exiting..."); exit(0); break; default: closesocket(src_fd); /* server */ break; } #endif }
error_t ftpOpenFile(FtpClientContext *context, const char_t *path, uint_t flags) { error_t error; uint_t replyCode; IpAddr ipAddr; uint16_t port; //Invalid context? if(context == NULL) return ERROR_INVALID_PARAMETER; //Open data socket context->dataSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); //Failed to open socket? if(!context->dataSocket) return ERROR_OPEN_FAILED; //Start of exception handling block do { //Bind the socket to a particular network interface? if(context->interface != NULL) { //Associate the socket with the relevant interface error = socketBindToInterface(context->dataSocket, context->interface); //Any error to report? if(error) break; } //Set timeout for blocking operations error = socketSetTimeout(context->dataSocket, FTP_CLIENT_DEFAULT_TIMEOUT); //Any error to report? if(error) break; //Check data transfer direction if(flags & (FTP_FOR_WRITING | FTP_FOR_APPENDING)) { //Maximize transmission throughput by using a large buffer error = socketSetTxBufferSize(context->dataSocket, FTP_CLIENT_SOCKET_MAX_TX_BUFFER_SIZE); //Any error to report? if(error) break; //Use a small buffer for the reception path error = socketSetRxBufferSize(context->dataSocket, FTP_CLIENT_SOCKET_MIN_RX_BUFFER_SIZE); //Any error to report? if(error) break; } else { //Use a small buffer for the transmission path error = socketSetTxBufferSize(context->dataSocket, FTP_CLIENT_SOCKET_MIN_TX_BUFFER_SIZE); //Any error to report? if(error) break; //Maximize reception throughput by using a large buffer error = socketSetRxBufferSize(context->dataSocket, FTP_CLIENT_SOCKET_MAX_RX_BUFFER_SIZE); //Any error to report? if(error) break; } //Set representation type if(flags & FTP_TEXT_TYPE) { //Use ASCII type error = ftpSetType(context, 'A'); //Any error to report? if(error) break; } else { //Use image type error = ftpSetType(context, 'I'); //Any error to report? if(error) break; } //Check transfer mode if(!context->passiveMode) { //Place the data socket in the listening state error = socketListen(context->dataSocket, 1); //Any error to report? if(error) break; //Retrieve local IP address error = socketGetLocalAddr(context->controlSocket, &ipAddr, NULL); //Any error to report? if(error) break; //Retrieve local port number error = socketGetLocalAddr(context->dataSocket, NULL, &port); //Any error to report? if(error) break; //Set the port to be used in data connection error = ftpSetPort(context, &ipAddr, port); //Any error to report? if(error) break; } else { //Enter passive mode error = ftpSetPassiveMode(context, &port); //Any error to report? if(error) break; //Establish data connection error = socketConnect(context->dataSocket, &context->serverAddr, port); //Connection to server failed? if(error) break; } //Format the command if(flags & FTP_FOR_WRITING) sprintf(context->buffer, "STOR %s\r\n", path); else if(flags & FTP_FOR_APPENDING) sprintf(context->buffer, "APPE %s\r\n", path); else sprintf(context->buffer, "RETR %s\r\n", path); //Send the command to the server error = ftpSendCommand(context, context->buffer, &replyCode); //Any error to report? if(error) break; //Check FTP response code if(!FTP_REPLY_CODE_1YZ(replyCode)) { //Report an error error = ERROR_UNEXPECTED_RESPONSE; break; } //Check transfer mode if(!context->passiveMode) { //Wait for the server to connect back to the client's data port Socket *socket = socketAccept(context->dataSocket, NULL, NULL); //No connection request? if(!socket) { //Report an error error = ERROR_FAILURE; break; } //Close the listening socket socketClose(context->dataSocket); //Save socket handle context->dataSocket = socket; //Set timeout for blocking operations error = socketSetTimeout(context->dataSocket, FTP_CLIENT_DEFAULT_TIMEOUT); //Any error to report? if(error) break; } //End of exception handling block } while(0); //Any error to report? if(error) { //Clean up side effects socketClose(context->dataSocket); context->dataSocket = NULL; } //Return status code return error; }
void tcpDiscardListenerTask(void *param) { error_t error; uint16_t clientPort; IpAddr clientIpAddr; Socket *serverSocket; Socket *clientSocket; DiscardServiceContext *context; OsTask *task; //Point to the listening socket serverSocket = (Socket *) param; //Main loop while(1) { //Accept an incoming connection clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort); //Check whether a valid connection request has been received if(!clientSocket) continue; //Debug message TRACE_INFO("Discard service: connection established with client %s port %" PRIu16 "\r\n", ipAddrToString(&clientIpAddr, NULL), clientPort); //Adjust timeout error = socketSetTimeout(clientSocket, DISCARD_TIMEOUT); //Any error to report? if(error) { //Close socket socketClose(clientSocket); //Wait for an incoming connection attempt continue; } //Allocate resources for the new connection context = osAllocMem(sizeof(DiscardServiceContext)); //Failed to allocate memory? if(!context) { //Close socket socketClose(clientSocket); //Wait for an incoming connection attempt continue; } //Record the handle of the newly created socket context->socket = clientSocket; //Create a task to service the current connection task = osCreateTask("TCP Discard Connection", tcpDiscardConnectionTask, context, DISCARD_SERVICE_STACK_SIZE, DISCARD_SERVICE_PRIORITY); //Did we encounter an error? if(task == OS_INVALID_HANDLE) { //Close socket socketClose(clientSocket); //Release resources osFreeMem(context); } } }