BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout ) { BOOL ret = FALSE; int res = 0; ULONG state; if (timeout > 0) { state = 1; ioctlsocket( conn->socket, FIONBIO, &state ); } if (connect( conn->socket, sockaddr, addr_len ) < 0) { res = sock_get_error( errno ); if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS) { #ifdef __REACTOS__ /* ReactOS: use select instead of poll */ fd_set outfd; struct timeval tv; FD_ZERO(&outfd); FD_SET(conn->socket, &outfd); tv.tv_sec = 0; tv.tv_usec = timeout * 1000; if (select( 0, NULL, &outfd, NULL, &tv ) > 0) #else struct pollfd pfd; pfd.fd = conn->socket; pfd.events = POLLOUT; if (poll( &pfd, 1, timeout ) > 0) #endif ret = TRUE; else res = sock_get_error( errno ); } } else ret = TRUE; if (timeout > 0) { state = 0; ioctlsocket( conn->socket, FIONBIO, &state ); } if (!ret) { WARN("unable to connect to host (%d)\n", res); set_last_error( res ); } return ret; }
/****************************************************************************** * NETCON_recv * Basically calls 'recv()' unless we should use SSL * number of chars received is put in *recvd */ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *recvd /* out */) { *recvd = 0; if (!len) return ERROR_SUCCESS; if (!connection->useSSL) { *recvd = recv(connection->socketFD, buf, len, flags); return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS; } else { #ifdef SONAME_LIBSSL if(!connection->ssl_s) { FIXME("not connected\n"); return ERROR_NOT_SUPPORTED; } *recvd = pSSL_read(connection->ssl_s, buf, len); /* Check if EOF was received */ if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) return ERROR_SUCCESS; return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED; #else return ERROR_NOT_SUPPORTED; #endif } }
/****************************************************************************** * NETCON_send * Basically calls 'send()' unless we should use SSL * number of chars send is put in *sent */ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, int *sent /* out */) { if (!connection->useSSL) { *sent = send(connection->socketFD, msg, len, flags); if (*sent == -1) return sock_get_error(errno); return ERROR_SUCCESS; } else { #ifdef SONAME_LIBSSL if(!connection->ssl_s) { FIXME("not connected\n"); return ERROR_NOT_SUPPORTED; } if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags); *sent = pSSL_write(connection->ssl_s, msg, len); if (*sent < 1 && len) return ERROR_INTERNET_CONNECTION_ABORTED; return ERROR_SUCCESS; #else return ERROR_NOT_SUPPORTED; #endif } }
BOOL netconn_close( netconn_t *conn ) { int res; if (conn->secure) { heap_free( conn->peek_msg_mem ); conn->peek_msg_mem = NULL; conn->peek_msg = NULL; conn->peek_len = 0; heap_free(conn->ssl_buf); conn->ssl_buf = NULL; heap_free(conn->extra_buf); conn->extra_buf = NULL; conn->extra_len = 0; DeleteSecurityContext(&conn->ssl_ctx); conn->secure = FALSE; } res = closesocket( conn->socket ); conn->socket = -1; if (res == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value) { int result; struct timeval tv; /* value is in milliseconds, convert to struct timeval */ if (value == INFINITE) { tv.tv_sec = 0; tv.tv_usec = 0; } else { tv.tv_sec = value / 1000; tv.tv_usec = (value % 1000) * 1000; } result = setsockopt(connection->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv)); if (result == -1) { WARN("setsockopt failed (%s)\n", strerror(errno)); return sock_get_error(errno); } return ERROR_SUCCESS; }
/****************************************************************************** * NETCON_send * Basically calls 'send()' unless we should use SSL * number of chars send is put in *sent */ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags, int *sent /* out */) { if (!NETCON_connected(connection)) return FALSE; if (!connection->useSSL) { *sent = send(connection->socketFD, msg, len, flags); if (*sent == -1) { INTERNET_SetLastError(sock_get_error(errno)); return FALSE; } return TRUE; } else { #ifdef SONAME_LIBSSL if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags); *sent = pSSL_write(connection->ssl_s, msg, len); if (*sent < 1 && len) return FALSE; return TRUE; #else return FALSE; #endif } }
/* wake anybody waiting on the socket event or send the associated message */ static void sock_wake_up( struct sock *sock ) { unsigned int events = sock->pmask & sock->mask; int i; if ( !events ) return; if (sock->event) { if (debug_level) fprintf(stderr, "signalling events %x ptr %p\n", events, sock->event ); set_event( sock->event ); } if (sock->window) { if (debug_level) fprintf(stderr, "signalling events %x win %08x\n", events, sock->window ); for (i = 0; i < FD_MAX_EVENTS; i++) { int event = event_bitorder[i]; if (sock->pmask & (1 << event)) { lparam_t lparam = (1 << event) | (sock_get_error(sock->errors[event]) << 16); post_message( sock->window, sock->message, sock->wparam, lparam ); } } sock->pmask = 0; sock_reselect( sock ); } }
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent ) { if (!netconn_connected( conn )) return FALSE; if (conn->secure) { const BYTE *ptr = msg; size_t chunk_size; *sent = 0; while(len) { chunk_size = min(len, conn->ssl_sizes.cbMaximumMessage); if(!send_ssl_chunk(conn, ptr, chunk_size)) return FALSE; *sent += chunk_size; ptr += chunk_size; len -= chunk_size; } return TRUE; } if ((*sent = sock_send( conn->socket, msg, len, 0 )) == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
/****************************************************************************** * NETCON_send * Basically calls 'send()' unless we should use SSL * number of chars send is put in *sent */ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, int *sent /* out */) { if(!connection->secure) { *sent = sock_send(connection->socket, msg, len, flags); if (*sent == -1) return sock_get_error(errno); return ERROR_SUCCESS; } else { const BYTE *ptr = msg; size_t chunk_size; *sent = 0; while(len) { chunk_size = min(len, connection->ssl_sizes.cbMaximumMessage); if(!send_ssl_chunk(connection, ptr, chunk_size)) return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; *sent += chunk_size; ptr += chunk_size; len -= chunk_size; } return ERROR_SUCCESS; } }
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) { int result; struct timeval tv; /* FIXME: we should probably store the timeout in the connection to set * when we do connect */ if (!NETCON_connected(connection)) return ERROR_SUCCESS; /* value is in milliseconds, convert to struct timeval */ tv.tv_sec = value / 1000; tv.tv_usec = (value % 1000) * 1000; result = setsockopt(connection->socketFD, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv, sizeof(tv)); if (result == -1) { WARN("setsockopt failed (%s)\n", strerror(errno)); return sock_get_error(errno); } return ERROR_SUCCESS; }
BOOL netconn_close( netconn_t *conn ) { int res; #ifdef SONAME_LIBSSL if (conn->secure) { heap_free( conn->peek_msg_mem ); conn->peek_msg_mem = NULL; conn->peek_msg = NULL; conn->peek_len = 0; pSSL_shutdown( conn->ssl_conn ); pSSL_free( conn->ssl_conn ); conn->ssl_conn = NULL; conn->secure = FALSE; } #endif res = closesocket( conn->socket ); conn->socket = -1; if (res == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
/****************************************************************************** * NETCON_close * Basically calls 'close()' unless we should use SSL */ BOOL NETCON_close(WININET_NETCONNECTION *connection) { int result; if (!NETCON_connected(connection)) return FALSE; #ifdef SONAME_LIBSSL if (connection->useSSL) { HeapFree(GetProcessHeap(),0,connection->peek_msg_mem); connection->peek_msg = NULL; connection->peek_msg_mem = NULL; connection->peek_len = 0; pSSL_shutdown(connection->ssl_s); pSSL_free(connection->ssl_s); connection->ssl_s = NULL; connection->useSSL = FALSE; } #endif result = closesocket(connection->socketFD); connection->socketFD = -1; if (result == -1) { INTERNET_SetLastError(sock_get_error(errno)); return FALSE; } return TRUE; }
static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD timeout) { int result; ULONG flag; assert(server->addr_len); result = netconn->socket = socket(server->addr.ss_family, SOCK_STREAM, 0); if(result != -1) { flag = 1; ioctlsocket(netconn->socket, FIONBIO, &flag); result = connect(netconn->socket, (struct sockaddr*)&server->addr, server->addr_len); if(result == -1) { if (sock_get_error(errno) == WSAEINPROGRESS) { struct pollfd pfd; int res; pfd.fd = netconn->socket; pfd.events = POLLOUT; res = poll(&pfd, 1, timeout); if (!res) { closesocket(netconn->socket); netconn->socket = -1; return ERROR_INTERNET_CANNOT_CONNECT; } else if (res > 0) { int err; socklen_t len = sizeof(err); if (!getsockopt(netconn->socket, SOL_SOCKET, SO_ERROR, (void *)&err, &len) && !err) result = 0; } } } if(result == -1) { closesocket(netconn->socket); netconn->socket = -1; } else { flag = 0; ioctlsocket(netconn->socket, FIONBIO, &flag); } } if(result == -1) return ERROR_INTERNET_CANNOT_CONNECT; #ifdef TCP_NODELAY flag = 1; result = setsockopt(netconn->socket, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag)); if(result < 0) WARN("setsockopt(TCP_NODELAY) failed\n"); #endif return ERROR_SUCCESS; }
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd ) { *recvd = 0; if (!netconn_connected( conn )) return FALSE; if (!len) return TRUE; if (conn->secure) { SIZE_T size, cread; BOOL res, eof; if (conn->peek_msg) { *recvd = min( len, conn->peek_len ); memcpy( buf, conn->peek_msg, *recvd ); conn->peek_len -= *recvd; conn->peek_msg += *recvd; if (conn->peek_len == 0) { heap_free( conn->peek_msg_mem ); conn->peek_msg_mem = NULL; conn->peek_msg = NULL; } /* check if we have enough data from the peek buffer */ if (!(flags & MSG_WAITALL) || *recvd == len) return TRUE; } size = *recvd; do { res = read_ssl_chunk(conn, (BYTE*)buf+size, len-size, &cread, &eof); if(!res) { WARN("read_ssl_chunk failed\n"); if(!size) return FALSE; break; } if(eof) { TRACE("EOF\n"); break; } size += cread; } while(!size || ((flags & MSG_WAITALL) && size < len)); TRACE("received %ld bytes\n", size); *recvd = size; return TRUE; } if ((*recvd = sock_recv( conn->socket, buf, len, flags )) == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout ) { BOOL ret = FALSE; int res = 0, state; if (timeout > 0) { state = 1; ioctlsocket( conn->socket, FIONBIO, &state ); } if (connect( conn->socket, sockaddr, addr_len ) < 0) { res = sock_get_error( errno ); if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS) { fd_set outfd; struct timeval tv; FD_ZERO(&outfd); FD_SET(conn->socket, &outfd); tv.tv_sec = 0; tv.tv_usec = timeout * 1000; if (select( 0, NULL, &outfd, NULL, &tv ) > 0) ret = TRUE; else res = sock_get_error( errno ); } } else ret = TRUE; if (timeout > 0) { state = 0; ioctlsocket( conn->socket, FIONBIO, &state ); } if (!ret) { WARN("unable to connect to host (%d)\n", res); set_last_error( res ); } return ret; }
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len ) { if (connect( conn->socket, sockaddr, addr_len ) == -1) { WARN("unable to connect to host (%s)\n", strerror(errno)); set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol ) { if ((conn->socket = socket( domain, type, protocol )) == -1) { WARN("unable to create socket (%s)\n", strerror(errno)); set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout ) { BOOL ret = FALSE; int res = 0, state; if (timeout > 0) { state = 1; ioctlsocket( conn->socket, FIONBIO, &state ); } if (connect( conn->socket, sockaddr, addr_len ) < 0) { res = sock_get_error( errno ); if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS) { struct pollfd pfd; pfd.fd = conn->socket; pfd.events = POLLOUT; if (poll( &pfd, 1, timeout ) > 0) ret = TRUE; else res = sock_get_error( errno ); } } else ret = TRUE; if (timeout > 0) { state = 0; ioctlsocket( conn->socket, FIONBIO, &state ); } if (!ret) { WARN("unable to connect to host (%d)\n", res); set_last_error( res ); } return ret; }
DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, netconn_t **ret) { netconn_t *netconn; int result, flag; if(useSSL) { DWORD res; TRACE("using SSL connection\n"); EnterCriticalSection(&init_ssl_cs); res = init_openssl(); LeaveCriticalSection(&init_ssl_cs); if(res != ERROR_SUCCESS) return res; } netconn = heap_alloc_zero(sizeof(*netconn)); if(!netconn) return ERROR_OUTOFMEMORY; netconn->useSSL = useSSL; netconn->socketFD = -1; netconn->security_flags = security_flags; list_init(&netconn->pool_entry); assert(server->addr_len); result = netconn->socketFD = socket(server->addr.ss_family, SOCK_STREAM, 0); if(result != -1) { result = connect(netconn->socketFD, (struct sockaddr*)&server->addr, server->addr_len); if(result == -1) closesocket(netconn->socketFD); } if(result == -1) { heap_free(netconn); return sock_get_error(errno); } #ifdef TCP_NODELAY flag = 1; result = setsockopt(netconn->socketFD, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag)); if(result < 0) WARN("setsockopt(TCP_NODELAY) failed\n"); #endif server_addref(server); netconn->server = server; *ret = netconn; return ERROR_SUCCESS; }
DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value ) { struct timeval tv; /* value is in milliseconds, convert to struct timeval */ tv.tv_sec = value / 1000; tv.tv_usec = (value % 1000) * 1000; if (setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1) { WARN("setsockopt failed (%s)\n", strerror( errno )); return sock_get_error( errno ); } return ERROR_SUCCESS; }
/****************************************************************************** * NETCON_create * Basically calls 'socket()' */ BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain, int type, int protocol) { #ifdef SONAME_LIBSSL if (connection->useSSL) return FALSE; #endif connection->socketFD = socket(domain, type, protocol); if (connection->socketFD == -1) { INTERNET_SetLastError(sock_get_error(errno)); return FALSE; } return TRUE; }
void Meta_send(char *mesg, size_t len) { int i; if (!options.reportToMetaServer) return; for (i = 0; i < NELEM(meta_servers); i++) { if (sock_send_dest(&contactSocket, meta_servers[i].addr, META_PORT, mesg, (int)len) != (int)len) { sock_get_error(&contactSocket); sock_send_dest(&contactSocket, meta_servers[i].addr, META_PORT, mesg, (int)len); } } }
/****************************************************************************** * NETCON_connect * Connects to the specified address. */ BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr, unsigned int addrlen) { int result; if (!NETCON_connected(connection)) return FALSE; result = connect(connection->socketFD, serv_addr, addrlen); if (result == -1) { WARN("Unable to connect to host (%s)\n", strerror(errno)); INTERNET_SetLastError(sock_get_error(errno)); closesocket(connection->socketFD); connection->socketFD = -1; return FALSE; } return TRUE; }
BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent ) { if (!netconn_connected( conn )) return FALSE; if (conn->secure) { #ifdef SONAME_LIBSSL if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags); *sent = pSSL_write( conn->ssl_conn, msg, len ); if (*sent < 1 && len) return FALSE; return TRUE; #else return FALSE; #endif } if ((*sent = send( conn->socket, msg, len, flags )) == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
BOOL netconn_close( netconn_t *conn ) { int res; if (conn->secure) { heap_free( conn->peek_msg_mem ); heap_free(conn->ssl_buf); heap_free(conn->extra_buf); DeleteSecurityContext(&conn->ssl_ctx); } res = closesocket( conn->socket ); release_host( conn->host ); heap_free(conn); if (res == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd ) { int ret; *recvd = 0; if (!netconn_connected( conn )) return FALSE; if (!len) return TRUE; if (conn->secure) { #ifdef SONAME_LIBSSL if (flags & ~(MSG_PEEK | MSG_WAITALL)) FIXME("SSL_read does not support the following flags: %08x\n", flags); /* this ugly hack is all for MSG_PEEK */ if (flags & MSG_PEEK && !conn->peek_msg) { if (!(conn->peek_msg = conn->peek_msg_mem = heap_alloc( len + 1 ))) return FALSE; } else if (flags & MSG_PEEK && conn->peek_msg) { if (len < conn->peek_len) FIXME("buffer isn't big enough, should we wrap?\n"); *recvd = min( len, conn->peek_len ); memcpy( buf, conn->peek_msg, *recvd ); return TRUE; } else if (conn->peek_msg) { *recvd = min( len, conn->peek_len ); memcpy( buf, conn->peek_msg, *recvd ); conn->peek_len -= *recvd; conn->peek_msg += *recvd; if (conn->peek_len == 0) { heap_free( conn->peek_msg_mem ); conn->peek_msg_mem = NULL; conn->peek_msg = NULL; } /* check if we have enough data from the peek buffer */ if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE; } ret = pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd ); if (ret < 0) return FALSE; /* check if EOF was received */ if (!ret && (pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_ZERO_RETURN || pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_SYSCALL )) { netconn_close( conn ); return TRUE; } if (flags & MSG_PEEK) /* must copy into buffer */ { conn->peek_len = ret; if (!ret) { heap_free( conn->peek_msg_mem ); conn->peek_msg_mem = NULL; conn->peek_msg = NULL; } else memcpy( conn->peek_msg, buf, ret ); } *recvd = ret; return TRUE; #else return FALSE; #endif } if ((*recvd = recv( conn->socket, buf, len, flags )) == -1) { set_last_error( sock_get_error( errno ) ); return FALSE; } return TRUE; }
/****************************************************************************** * NETCON_recv * Basically calls 'recv()' unless we should use SSL * number of chars received is put in *recvd */ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, blocking_mode_t mode, int *recvd) { *recvd = 0; if (!len) return ERROR_SUCCESS; if (!connection->secure) { int flags = 0; switch(mode) { case BLOCKING_ALLOW: break; case BLOCKING_DISALLOW: flags = WINE_MSG_DONTWAIT; break; case BLOCKING_WAITALL: flags = MSG_WAITALL; break; } set_socket_blocking(connection->socket, mode); *recvd = sock_recv(connection->socket, buf, len, flags); return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS; } else { SIZE_T size = 0, cread; BOOL eof; DWORD res; if(connection->peek_msg) { size = min(len, connection->peek_len); memcpy(buf, connection->peek_msg, size); connection->peek_len -= size; connection->peek_msg += size; if(!connection->peek_len) { heap_free(connection->peek_msg_mem); connection->peek_msg_mem = connection->peek_msg = NULL; } /* check if we have enough data from the peek buffer */ if(mode != BLOCKING_WAITALL || size == len) { *recvd = size; return ERROR_SUCCESS; } mode = BLOCKING_DISALLOW; } do { res = read_ssl_chunk(connection, (BYTE*)buf+size, len-size, mode, &cread, &eof); if(res != ERROR_SUCCESS) { if(res == WSAEWOULDBLOCK) { if(size) res = ERROR_SUCCESS; }else { WARN("read_ssl_chunk failed\n"); } break; } if(eof) { TRACE("EOF\n"); break; } size += cread; }while(!size || (mode == BLOCKING_WAITALL && size < len)); TRACE("received %zd bytes\n", size); *recvd = size; return res; } }
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen ) { struct pollfd pfd; BOOL ret = FALSE; DWORD recvd = 0; if (!netconn_connected( conn )) return FALSE; if (conn->secure) { #ifdef SONAME_LIBSSL long timeout; timeout = pSSL_CTX_get_timeout( ctx ); pSSL_CTX_set_timeout( ctx, DEFAULT_RECEIVE_TIMEOUT ); while (recvd < *buflen) { int dummy; if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy )) { set_last_error( ERROR_CONNECTION_ABORTED ); break; } if (buffer[recvd] == '\n') { ret = TRUE; break; } if (buffer[recvd] != '\r') recvd++; } pSSL_CTX_set_timeout( ctx, timeout ); if (ret) { buffer[recvd++] = 0; *buflen = recvd; TRACE("received line %s\n", debugstr_a(buffer)); } return ret; #else return FALSE; #endif } pfd.fd = conn->socket; pfd.events = POLLIN; while (recvd < *buflen) { if (poll( &pfd, 1, DEFAULT_RECEIVE_TIMEOUT * 1000 ) > 0) { int res; if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0) { if (res == -1) set_last_error( sock_get_error( errno ) ); break; } if (buffer[recvd] == '\n') { ret = TRUE; break; } if (buffer[recvd] != '\r') recvd++; } else { set_last_error( ERROR_WINHTTP_TIMEOUT ); break; } } if (ret) { buffer[recvd++] = 0; *buflen = recvd; TRACE("received line %s\n", debugstr_a(buffer)); } return ret; }
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen ) { struct pollfd pfd; BOOL ret = FALSE; DWORD recvd = 0; if (!netconn_connected( conn )) return FALSE; if (conn->secure) { #ifdef SONAME_LIBSSL while (recvd < *buflen) { int dummy; if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy )) { set_last_error( ERROR_CONNECTION_ABORTED ); break; } if (buffer[recvd] == '\n') { ret = TRUE; break; } if (buffer[recvd] != '\r') recvd++; } if (ret) { buffer[recvd++] = 0; *buflen = recvd; TRACE("received line %s\n", debugstr_a(buffer)); } return ret; #else return FALSE; #endif } pfd.fd = conn->socket; pfd.events = POLLIN; while (recvd < *buflen) { int timeout, res; struct timeval tv; socklen_t len = sizeof(tv); if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1)) timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000; else timeout = -1; if (poll( &pfd, 1, timeout ) > 0) { if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0) { if (res == -1) set_last_error( sock_get_error( errno ) ); break; } if (buffer[recvd] == '\n') { ret = TRUE; break; } if (buffer[recvd] != '\r') recvd++; } else { set_last_error( ERROR_WINHTTP_TIMEOUT ); break; } } if (ret) { buffer[recvd++] = 0; *buflen = recvd; TRACE("received line %s\n", debugstr_a(buffer)); } return ret; }
/****************************************************************************** * NETCON_getNextLine */ BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer) { TRACE("\n"); if (!NETCON_connected(connection)) return FALSE; if (!connection->useSSL) { struct pollfd pfd; BOOL bSuccess = FALSE; DWORD nRecv = 0; pfd.fd = connection->socketFD; pfd.events = POLLIN; while (nRecv < *dwBuffer) { if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0) { if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0) { INTERNET_SetLastError(sock_get_error(errno)); goto lend; } if (lpszBuffer[nRecv] == '\n') { bSuccess = TRUE; break; } if (lpszBuffer[nRecv] != '\r') nRecv++; } else { INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT); goto lend; } } lend: /* FIXME: don't use labels */ if (bSuccess) { lpszBuffer[nRecv++] = '\0'; *dwBuffer = nRecv; TRACE(":%u %s\n", nRecv, lpszBuffer); return TRUE; } else { return FALSE; } } else { #ifdef SONAME_LIBSSL long prev_timeout; DWORD nRecv = 0; BOOL success = TRUE; prev_timeout = pSSL_CTX_get_timeout(ctx); pSSL_CTX_set_timeout(ctx, RESPONSE_TIMEOUT); while (nRecv < *dwBuffer) { int recv = 1; if (!NETCON_recv(connection, &lpszBuffer[nRecv], 1, 0, &recv)) { INTERNET_SetLastError(ERROR_CONNECTION_ABORTED); success = FALSE; } if (lpszBuffer[nRecv] == '\n') { success = TRUE; break; } if (lpszBuffer[nRecv] != '\r') nRecv++; } pSSL_CTX_set_timeout(ctx, prev_timeout); if (success) { lpszBuffer[nRecv++] = '\0'; *dwBuffer = nRecv; TRACE("_SSL:%u %s\n", nRecv, lpszBuffer); return TRUE; } return FALSE; #else return FALSE; #endif } }