From 5ac03256db0fe4ca7e3ad1117d096c3a76368b76 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 9 Jan 2015 09:46:07 +0100 Subject: backported CyaSSL/OpenSSL support for internal webserver instead of MatrixSSL --- release/src/router/matrixssl/examples/sslSocket.c | 1025 --------------------- 1 file changed, 1025 deletions(-) delete mode 100644 release/src/router/matrixssl/examples/sslSocket.c (limited to 'release/src/router/matrixssl/examples/sslSocket.c') diff --git a/release/src/router/matrixssl/examples/sslSocket.c b/release/src/router/matrixssl/examples/sslSocket.c deleted file mode 100644 index 39c51871..00000000 --- a/release/src/router/matrixssl/examples/sslSocket.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * socketLayer.c - * Release $Name: MATRIXSSL_1_8_8_OPEN $ - * - * Sample SSL socket layer for MatrixSSL example exectuables - */ -/* - * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved. - * The latest version of this code is available at http://www.matrixssl.org - * - * This software is open source; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This General Public License does NOT permit incorporating this software - * into proprietary programs. If you are unable to comply with the GPL, a - * commercial license for this software may be purchased from PeerSec Networks - * at http://www.peersec.com - * - * This program is distributed in WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * http://www.gnu.org/copyleft/gpl.html - */ -/******************************************************************************/ - -#include -#include -#include "sslSocket.h" - -/******************************************************************************/ -/* - An EXAMPLE socket layer API for the MatrixSSL library. -*/ - -/******************************************************************************/ -/* - Server side. Set up a listen socket. This code is not specific to SSL. -*/ -SOCKET socketListen(short port, int *err) -{ - struct sockaddr_in addr; - SOCKET fd; - int rc; - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "Error creating listen socket\n"); - *err = getSocketError(); - return INVALID_SOCKET; - } -/* - Make sure the socket is not inherited by exec'd processes - Set the REUSE flag to minimize the number of sockets in TIME_WAIT -*/ - fcntl(fd, F_SETFD, FD_CLOEXEC); - rc = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - fprintf(stderr, - "Can't bind socket. Port in use or insufficient privilege\n"); - *err = getSocketError(); - return INVALID_SOCKET; - } - if (listen(fd, SOMAXCONN) < 0) { - fprintf(stderr, "Error listening on socket\n"); - *err = getSocketError(); - return INVALID_SOCKET; - } - return fd; -} - -/******************************************************************************/ -/* - Server side. Accept a new socket connection off our listen socket. - This code is not specific to SSL. -*/ -SOCKET socketAccept(SOCKET listenfd, int *err) -{ - struct sockaddr_in addr; - SOCKET fd; - int len; -/* - Wait(blocking)/poll(non-blocking) for an incoming connection -*/ - len = sizeof(addr); - if ((fd = accept(listenfd, (struct sockaddr *)&addr, &len)) - == INVALID_SOCKET) { - *err = getSocketError(); - if (*err != WOULD_BLOCK) { - fprintf(stderr, "Error %d accepting new socket\n", *err); - } - return INVALID_SOCKET; - } -/* - fd is the newly accepted socket. Disable Nagle on this socket. - Set blocking mode as default -*/ -/* fprintf(stdout, "Connection received from %d.%d.%d.%d\n", - addr.sin_addr.S_un.S_un_b.s_b1, - addr.sin_addr.S_un.S_un_b.s_b2, - addr.sin_addr.S_un.S_un_b.s_b3, - addr.sin_addr.S_un.S_un_b.s_b4); -*/ - setSocketNodelay(fd); - setSocketBlock(fd); - return fd; -} - -/******************************************************************************/ -/* - Client side. Open a socket connection to a remote ip and port. - This code is not specific to SSL. -*/ -SOCKET socketConnect(char *ip, short port, int *err) -{ - struct sockaddr_in addr; - SOCKET fd; - int rc; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "Error creating socket\n"); - *err = getSocketError(); - return INVALID_SOCKET; - } -/* - Make sure the socket is not inherited by exec'd processes - Set the REUSEADDR flag to minimize the number of sockets in TIME_WAIT -*/ - fcntl(fd, F_SETFD, FD_CLOEXEC); - rc = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - setSocketNodelay(fd); -/* - Turn on blocking mode for the connecting socket -*/ - setSocketBlock(fd); - - memset((char *) &addr, 0x0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(ip); - rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); -#if WIN - if (rc != 0) { -#else - if (rc < 0) { -#endif - *err = getSocketError(); - return INVALID_SOCKET; - } - return fd; -} - -/******************************************************************************/ -/* - Server side. Accept an incomming SSL connection request. - 'conn' will be filled in with information about the accepted ssl connection - - return -1 on error, 0 on success, or WOULD_BLOCK for non-blocking sockets -*/ -int sslAccept(sslConn_t **cpp, SOCKET fd, sslKeys_t *keys, - int (*certValidator)(sslCertInfo_t *t, void *arg), int flags) -{ - sslConn_t *conn; - unsigned char buf[1024]; - int status, rc; -/* - Associate a new ssl session with this socket. The session represents - the state of the ssl protocol over this socket. Session caching is - handled automatically by this api. -*/ - conn = calloc(sizeof(sslConn_t), 1); - conn->fd = fd; - if (matrixSslNewSession(&conn->ssl, keys, NULL, - SSL_FLAGS_SERVER | flags) < 0) { - sslFreeConnection(&conn); - return -1; - } -/* - MatrixSSL doesn't provide buffers for data internally. Define them - here to support buffered reading and writing for non-blocking sockets. - Although it causes quite a bit more work, we support dynamically growing - the buffers as needed. Alternately, we could define 16K buffers here - and not worry about growing them. -*/ - memset(&conn->inbuf, 0x0, sizeof(sslBuf_t)); - conn->insock.size = 1024; - conn->insock.start = conn->insock.end = conn->insock.buf = - (unsigned char *)malloc(conn->insock.size); - conn->outsock.size = 1024; - conn->outsock.start = conn->outsock.end = conn->outsock.buf = - (unsigned char *)malloc(conn->outsock.size); - conn->inbuf.size = 0; - conn->inbuf.start = conn->inbuf.end = conn->inbuf.buf = NULL; - *cpp = conn; - -readMore: - rc = sslRead(conn, buf, sizeof(buf), &status); -/* - Reading handshake records should always return 0 bytes, we aren't - expecting any data yet. -*/ - if (rc == 0) { - if (status == SSLSOCKET_EOF || status == SSLSOCKET_CLOSE_NOTIFY) { - sslFreeConnection(&conn); - return -1; - } - if (matrixSslHandshakeIsComplete(conn->ssl) == 0) { - goto readMore; - } - } else if (rc > 0) { - socketAssert(0); - return -1; - } else { - fprintf(stderr, "sslRead error in sslAccept\n"); - sslFreeConnection(&conn); - return -1; - } - *cpp = conn; - - return 0; -} - -/******************************************************************************/ -/* - Client side. Make a socket connection and go through the SSL handshake - phase in blocking mode. The last parameter is an optional function - callback for user-level certificate validation. NULL if not needed. -*/ -int sslConnect(sslConn_t **cpp, SOCKET fd, sslKeys_t *keys, - sslSessionId_t *id, short cipherSuite, - int (*certValidator)(sslCertInfo_t *t, void *arg)) -{ - sslConn_t *conn; - -/* - Create a new SSL session for the new socket and register the - user certificate validator -*/ - conn = calloc(sizeof(sslConn_t), 1); - conn->fd = fd; - if (matrixSslNewSession(&conn->ssl, keys, id, 0) < 0) { - sslFreeConnection(&conn); - return -1; - } - matrixSslSetCertValidator(conn->ssl, certValidator, keys); - - *cpp = sslDoHandshake(conn, cipherSuite); - - if (*cpp == NULL) { - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - Construct the initial HELLO message to send to the server and initiate - the SSL handshake. Can be used in the re-handshake scenario as well. -*/ -sslConn_t *sslDoHandshake(sslConn_t *conn, short cipherSuite) -{ - char buf[1024]; - int bytes, status, rc; - -/* - MatrixSSL doesn't provide buffers for data internally. Define them - here to support buffered reading and writing for non-blocking sockets. - Although it causes quite a bit more work, we support dynamically growing - the buffers as needed. Alternately, we could define 16K buffers here - and not worry about growing them. -*/ - conn->insock.size = 1024; - conn->insock.start = conn->insock.end = conn->insock.buf = - (unsigned char *)malloc(conn->insock.size); - conn->outsock.size = 1024; - conn->outsock.start = conn->outsock.end = conn->outsock.buf = - (unsigned char *)malloc(conn->outsock.size); - conn->inbuf.size = 0; - conn->inbuf.start = conn->inbuf.end = conn->inbuf.buf = NULL; - - bytes = matrixSslEncodeClientHello(conn->ssl, &conn->outsock, cipherSuite); - if (bytes < 0) { - socketAssert(bytes < 0); - goto error; - } -/* - Send the hello with a blocking write -*/ - if (psSocketWrite(conn->fd, &conn->outsock) < 0) { - fprintf(stdout, "Error in socketWrite\n"); - goto error; - } - conn->outsock.start = conn->outsock.end = conn->outsock.buf; -/* - Call sslRead to work through the handshake. Not actually expecting - data back, so the finished case is simply when the handshake is - complete. -*/ -readMore: - rc = sslRead(conn, buf, sizeof(buf), &status); -/* - Reading handshake records should always return 0 bytes, we aren't - expecting any data yet. -*/ - if (rc == 0) { - if (status == SSLSOCKET_EOF || status == SSLSOCKET_CLOSE_NOTIFY) { - goto error; - } - if (matrixSslHandshakeIsComplete(conn->ssl) == 0) { - goto readMore; - } - } else if (rc > 0) { - fprintf(stderr, "sslRead got %d data in sslDoHandshake %s\n", rc, buf); - goto readMore; - } else { - fprintf(stderr, "sslRead error in sslDoHandhake\n"); - goto error; - } - - return conn; - -error: - sslFreeConnection(&conn); - return NULL; -} - -/******************************************************************************/ -/* - An example socket sslRead implementation that handles the ssl handshake - transparently. Caller passes in allocated buf and length. - - Return codes are as follows: - - -1 return code is an error. If a socket level error, error code is - contained in status parameter. If using a non-blocking socket - implementation the caller should check for non-fatal errors such as - WOULD_BLOCK before closing the connection. A zero value - in status indicates an error with this routine. - - A positive integer return code is the number of bytes successfully read - into the supplied buffer. User can call sslRead again on the updated - buffer is there is more to be read. - - 0 return code indicates the read was successful, but there was no data - to be returned. If status is set to zero, this is a case internal - to the sslAccept and sslConnect functions that a handshake - message has been exchanged. If status is set to SOCKET_EOF - the connection has been closed by the other side. - -*/ -int sslRead(sslConn_t *cp, char *buf, int len, int *status) -{ - int bytes, rc, remaining; - unsigned char error, alertLevel, alertDescription, performRead; - - *status = 0; - - if (cp->ssl == NULL || len <= 0) { - return -1; - } -/* - If inbuf is valid, then we have previously decoded data that must be - returned, return as much as possible. Once all buffered data is - returned, free the inbuf. -*/ - if (cp->inbuf.buf) { - if (cp->inbuf.start < cp->inbuf.end) { - remaining = (int)(cp->inbuf.end - cp->inbuf.start); - bytes = (int)min(len, remaining); - memcpy(buf, cp->inbuf.start, bytes); - cp->inbuf.start += bytes; - return bytes; - } - free(cp->inbuf.buf); - cp->inbuf.buf = NULL; - } -/* - Pack the buffered socket data (if any) so that start is at zero. -*/ - if (cp->insock.buf < cp->insock.start) { - if (cp->insock.start == cp->insock.end) { - cp->insock.start = cp->insock.end = cp->insock.buf; - } else { - memmove(cp->insock.buf, cp->insock.start, cp->insock.end - cp->insock.start); - cp->insock.end -= (cp->insock.start - cp->insock.buf); - cp->insock.start = cp->insock.buf; - } - } -/* - Read up to as many bytes as there are remaining in the buffer. We could - Have encrypted data already cached in conn->insock, but might as well read more - if we can. -*/ - performRead = 0; -readMore: - if (cp->insock.end == cp->insock.start || performRead) { - performRead = 1; - bytes = recv(cp->fd, (char *)cp->insock.end, - (int)((cp->insock.buf + cp->insock.size) - cp->insock.end), MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - *status = getSocketError(); - return -1; - } - if (bytes == 0) { - *status = SSLSOCKET_EOF; - return 0; - } - cp->insock.end += bytes; - } -/* - Define a temporary sslBuf -*/ - cp->inbuf.start = cp->inbuf.end = cp->inbuf.buf = malloc(len); - cp->inbuf.size = len; -/* - Decode the data we just read from the socket -*/ -decodeMore: - error = 0; - alertLevel = 0; - alertDescription = 0; - - rc = matrixSslDecode(cp->ssl, &cp->insock, &cp->inbuf, &error, &alertLevel, - &alertDescription); - switch (rc) { -/* - Successfully decoded a record that did not return data or require a response. -*/ - case SSL_SUCCESS: - return 0; -/* - Successfully decoded an application data record, and placed in tmp buf -*/ - case SSL_PROCESS_DATA: -/* - Copy as much as we can from the temp buffer into the caller's buffer - and leave the remainder in conn->inbuf until the next call to read - It is possible that len > data in buffer if the encoded record - was longer than len, but the decoded record isn't! -*/ - rc = (int)(cp->inbuf.end - cp->inbuf.start); - rc = min(rc, len); - memcpy(buf, cp->inbuf.start, rc); - cp->inbuf.start += rc; - return rc; -/* - We've decoded a record that requires a response into tmp - If there is no data to be flushed in the out buffer, we can write out - the contents of the tmp buffer. Otherwise, we need to append the data - to the outgoing data buffer and flush it out. -*/ - case SSL_SEND_RESPONSE: - bytes = send(cp->fd, (char *)cp->inbuf.start, - (int)(cp->inbuf.end - cp->inbuf.start), MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - *status = getSocketError(); - if (*status != WOULD_BLOCK) { - fprintf(stdout, "Socket send error: %d\n", *status); - goto readError; - } - *status = 0; - } - cp->inbuf.start += bytes; - if (cp->inbuf.start < cp->inbuf.end) { -/* - This must be a non-blocking socket since it didn't all get sent - out and there was no error. We want to finish the send here - simply because we are likely in the SSL handshake. -*/ - setSocketBlock(cp->fd); - bytes = send(cp->fd, (char *)cp->inbuf.start, - (int)(cp->inbuf.end - cp->inbuf.start), MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - *status = getSocketError(); - goto readError; - } - cp->inbuf.start += bytes; - socketAssert(cp->inbuf.start == cp->inbuf.end); -/* - Can safely set back to non-blocking because we wouldn't - have got here if this socket wasn't non-blocking to begin with. -*/ - setSocketNonblock(cp->fd); - } - cp->inbuf.start = cp->inbuf.end = cp->inbuf.buf; - return 0; -/* - There was an error decoding the data, or encoding the out buffer. - There may be a response data in the out buffer, so try to send. - We try a single hail-mary send of the data, and then close the socket. - Since we're closing on error, we don't worry too much about a clean flush. -*/ - case SSL_ERROR: - fprintf(stderr, "SSL: Closing on protocol error %d\n", error); - if (cp->inbuf.start < cp->inbuf.end) { - setSocketNonblock(cp->fd); - bytes = send(cp->fd, (char *)cp->inbuf.start, - (int)(cp->inbuf.end - cp->inbuf.start), MSG_NOSIGNAL); - } - goto readError; -/* - We've decoded an alert. The level and description passed into - matrixSslDecode are filled in with the specifics. -*/ - case SSL_ALERT: - if (alertDescription == SSL_ALERT_CLOSE_NOTIFY) { - *status = SSLSOCKET_CLOSE_NOTIFY; - goto readZero; - } - fprintf(stderr, "SSL: Closing on client alert %d: %d\n", - alertLevel, alertDescription); - goto readError; -/* - We have a partial record, we need to read more data off the socket. - If we have a completely full conn->insock buffer, we'll need to grow it - here so that we CAN read more data when called the next time. -*/ - case SSL_PARTIAL: - if (cp->insock.start == cp->insock.buf && cp->insock.end == - (cp->insock.buf + cp->insock.size)) { - if (cp->insock.size > SSL_MAX_BUF_SIZE) { - goto readError; - } - cp->insock.size *= 2; - cp->insock.start = cp->insock.buf = - (unsigned char *)realloc(cp->insock.buf, cp->insock.size); - cp->insock.end = cp->insock.buf + (cp->insock.size / 2); - } - if (!performRead) { - performRead = 1; - free(cp->inbuf.buf); - cp->inbuf.buf = NULL; - goto readMore; - } else { - goto readZero; - } -/* - The out buffer is too small to fit the decoded or response - data. Increase the size of the buffer and call decode again -*/ - case SSL_FULL: - cp->inbuf.size *= 2; - if (cp->inbuf.buf != (unsigned char*)buf) { - free(cp->inbuf.buf); - cp->inbuf.buf = NULL; - } - cp->inbuf.start = cp->inbuf.end = cp->inbuf.buf = - (unsigned char *)malloc(cp->inbuf.size); - goto decodeMore; - } -/* - We consolidated some of the returns here because we must ensure - that conn->inbuf is cleared if pointing at caller's buffer, otherwise - it will be freed later on. -*/ -readZero: - if (cp->inbuf.buf == (unsigned char*)buf) { - cp->inbuf.buf = NULL; - } - return 0; -readError: - if (cp->inbuf.buf == (unsigned char*)buf) { - cp->inbuf.buf = NULL; - } - return -1; -} - -/******************************************************************************/ -/* - Example sslWrite functionality. Takes care of encoding the input buffer - and sending it out on the connection. - - Return codes are as follows: - - -1 return code is an error. If a socket level error, error code is - contained in status. If using a non-blocking socket - implementation the caller should check for non-fatal errors such as - WOULD_BLOCK before closing the connection. A zero value - in status indicates an error with this routine. - - A positive integer return value indicates the number of bytes succesfully - written on the connection. Should always match the len parameter. - - 0 return code indicates the write must be called again with the same - parameters. -*/ -int sslWrite(sslConn_t *cp, char *buf, int len, int *status) -{ - int rc; - - *status = 0; -/* - Pack the buffered socket data (if any) so that start is at zero. -*/ - if (cp->outsock.buf < cp->outsock.start) { - if (cp->outsock.start == cp->outsock.end) { - cp->outsock.start = cp->outsock.end = cp->outsock.buf; - } else { - memmove(cp->outsock.buf, cp->outsock.start, cp->outsock.end - cp->outsock.start); - cp->outsock.end -= (cp->outsock.start - cp->outsock.buf); - cp->outsock.start = cp->outsock.buf; - } - } -/* - If there is buffered output data, the caller must be trying to - send the same amount of data as last time. We don't support - sending additional data until the original buffered request has - been completely sent. -*/ - if (cp->outBufferCount > 0 && len != cp->outBufferCount) { - socketAssert(len != cp->outBufferCount); - return -1; - } -/* - If we don't have buffered data, encode the caller's data -*/ - if (cp->outBufferCount == 0) { -retryEncode: - rc = matrixSslEncode(cp->ssl, (unsigned char *)buf, len, &cp->outsock); - switch (rc) { - case SSL_ERROR: - return -1; - case SSL_FULL: - if (cp->outsock.size > SSL_MAX_BUF_SIZE) { - return -1; - } - cp->outsock.size *= 2; - cp->outsock.buf = - (unsigned char *)realloc(cp->outsock.buf, cp->outsock.size); - cp->outsock.end = cp->outsock.buf + (cp->outsock.end - cp->outsock.start); - cp->outsock.start = cp->outsock.buf; - goto retryEncode; - } - } -/* - We've got data to send. -*/ - rc = send(cp->fd, (char *)cp->outsock.start, - (int)(cp->outsock.end - cp->outsock.start), MSG_NOSIGNAL); - if (rc == SOCKET_ERROR) { - *status = getSocketError(); - return -1; - } - cp->outsock.start += rc; -/* - If we wrote it all return the length, otherwise remember the number of - bytes passed in, and return 0 to be called again later. -*/ - if (cp->outsock.start == cp->outsock.end) { - cp->outBufferCount = 0; - return len; - } - cp->outBufferCount = len; - return 0; -} - -/******************************************************************************/ -/* - Send a close alert -*/ -void sslWriteClosureAlert(sslConn_t *cp) -{ - if (cp != NULL) { - cp->outsock.start = cp->outsock.end = cp->outsock.buf; - matrixSslEncodeClosureAlert(cp->ssl, &cp->outsock); - setSocketNonblock(cp->fd); - send(cp->fd, cp->outsock.start, - (int)(cp->outsock.end - cp->outsock.start), MSG_NOSIGNAL); - } -} - -/******************************************************************************/ -/* - Server initiated rehandshake. Builds and sends the HELLO_REQUEST message -*/ -void sslRehandshake(sslConn_t *cp) -{ - matrixSslEncodeHelloRequest(cp->ssl, &cp->outsock); - psSocketWrite(cp->fd, &cp->outsock); - cp->outsock.start = cp->outsock.end = cp->outsock.buf; -} - -/******************************************************************************/ -/* - Close a seesion that was opened with sslAccept or sslConnect and - free the insock and outsock buffers -*/ -void sslFreeConnection(sslConn_t **cpp) -{ - sslConn_t *conn; - - conn = *cpp; - matrixSslDeleteSession(conn->ssl); - conn->ssl = NULL; - if (conn->insock.buf) { - free(conn->insock.buf); - conn->insock.buf = NULL; - } - if (conn->outsock.buf) { - free(conn->outsock.buf); - conn->outsock.buf = NULL; - } - if (conn->inbuf.buf) { - free(conn->inbuf.buf); - conn->inbuf.buf = NULL; - } - free(conn); - *cpp = NULL; -} - -/******************************************************************************/ -/* - free the insock and outsock buffers -*/ -void sslFreeConnectionBuffers(sslConn_t **cpp) -{ - sslConn_t *conn; - - conn = *cpp; - if (conn->insock.buf) { - free(conn->insock.buf); - conn->insock.buf = NULL; - } - if (conn->outsock.buf) { - free(conn->outsock.buf); - conn->outsock.buf = NULL; - } - if (conn->inbuf.buf) { - free(conn->inbuf.buf); - conn->inbuf.buf = NULL; - } -} - -/******************************************************************************/ -/* - Set the socket to non blocking mode and perform a few extra tricks - to make sure the socket closes down cross platform -*/ -void socketShutdown(SOCKET sock) -{ - char buf[32]; - - if (sock != INVALID_SOCKET) { - setSocketNonblock(sock); - if (shutdown(sock, 1) >= 0) { - while (recv(sock, buf, sizeof(buf), 0) > 0); - } - closesocket(sock); - } -} - -/******************************************************************************/ -/* - Perform a blocking write of data to a socket -*/ -int psSocketWrite(SOCKET sock, sslBuf_t *out) -{ - unsigned char *s; - int bytes; - - s = out->start; - while (out->start < out->end) { - bytes = send(sock, out->start, (int)(out->end - out->start), MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - return -1; - } - out->start += bytes; - } - return (int)(out->start - s); -} - -int psSocketRead(SOCKET sock, sslBuf_t **out, int *status) -{ - sslBuf_t *local; - char *c; - int bytes; - - local = *out; - c = local->start; - - bytes = recv(sock, c, (int)((local->buf + local->size) - local->end), MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - *status = getSocketError(); - return -1; - } - if (bytes == 0) { - *status = SSLSOCKET_EOF; - return 0; - } - local->end += bytes; - return bytes; -} - -/******************************************************************************/ -/* - Turn on socket blocking mode (and set CLOEXEC on LINUX for kicks). -*/ -void setSocketBlock(SOCKET sock) -{ -#if _WIN32 - int block = 0; - ioctlsocket(sock, FIONBIO, &block); -#elif LINUX - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) & ~O_NONBLOCK); - fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif -} - -/******************************************************************************/ -/* - Turn off socket blocking mode. -*/ -void setSocketNonblock(SOCKET sock) -{ -#if _WIN32 - int block = 1; - ioctlsocket(sock, FIONBIO, &block); -#elif LINUX - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); -#endif -} - -/******************************************************************************/ -/* - Disable the Nagle algorithm for less latency in RPC - http://www.faqs.org/rfcs/rfc896.html - http://www.w3.org/Protocols/HTTP/Performance/Nagle/ -*/ -void setSocketNodelay(SOCKET sock) -{ -#if _WIN32 - BOOL tmp = TRUE; -#else - int tmp = 1; -#endif /* WIN32 */ - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); -} - -/******************************************************************************/ -/* - Set a breakpoint in this function to catch asserts. - This function is called whenever an assert is triggered. Useful because - VisualStudio often won't show the right line of code if DebugBreak() is - called directly, and abort() may not be desireable on LINUX. -*/ -void breakpoint() -{ - static int preventInline = 0; -#if _WIN32 - DebugBreak(); -#elif LINUX - abort(); -#endif -} - - -/******************************************************************************/ -/* - Parse an ASCII command line string. Assumes a NULL terminated space - separated list of command line arguments. Uses this info to create an argv - array. - - Notes: - handles double quotes - args gets hacked up! can't pass in static string! - not thread safe, so should be called b4 any thread creation - we currently hardcode argv[0] cause none of our apps need it - */ - -#if WINCE || VXWORKS - -void parseCmdLineArgs(char *args, int *pargc, char ***pargv) -{ - char **argv; - char *ptr; - int size, i; - -/* - * Figure out the number of elements in our argv array. - * We know we need an argv array of at least 3, since we have the - * program name, an argument, and a NULL in the array. - */ - for (size = 3, ptr = args; ptr && *ptr != '\0'; ptr++) { - if (isspace(*ptr)) { - size++; - while (isspace(*ptr)) { - ptr++; - } - if (*ptr == '\0') { - break; - } - } - } -/* - * This is called from main, so don't use psMalloc here or - * all the stats will be wrong. - */ - argv = (char**) malloc(size * sizeof(char*)); - *pargv = argv; - - for (i = 1, ptr = args; ptr && *ptr != '\0'; i++) { - while (isspace(*ptr)) { - ptr++; - } - if (*ptr == '\0') { - break; - } -/* - * Handle double quoted arguments. Treat everything within - * the double quote as one arg. - */ - if (*ptr == '"') { - ptr++; - argv[i] = ptr; - while ((*ptr != '\0') && (*ptr != '"')) { - ptr++; - } - } else { - argv[i] = ptr; - while (*ptr != '\0' && !isspace(*ptr)) { - ptr++; - } - } - if (*ptr != '\0') { - *ptr = '\0'; - ptr++; - } - } - argv[i] = NULL; - *pargc = i ; - - argv[0] = "PeerSec"; - for (ptr = argv[0]; *ptr; ptr++) { - if (*ptr == '\\') { - *ptr = '/'; - } - } -} -#endif /* WINCE || VXWORKS */ - -#ifdef WINCE - -/******************************************************************************/ -/* - The following functions implement a unixlike time() function for WINCE. - - NOTE: this code is copied from the os layer in win.c to expose it for use - in example applications. - */ - -static FILETIME YearToFileTime(WORD wYear) -{ - SYSTEMTIME sbase; - FILETIME fbase; - - sbase.wYear = wYear; - sbase.wMonth = 1; - sbase.wDayOfWeek = 1; //assumed - sbase.wDay = 1; - sbase.wHour = 0; - sbase.wMinute = 0; - sbase.wSecond = 0; - sbase.wMilliseconds = 0; - - SystemTimeToFileTime( &sbase, &fbase ); - - return fbase; -} - -time_t time() { - - __int64 time1, time2, iTimeDiff; - FILETIME fileTime1, fileTime2; - SYSTEMTIME sysTime; - -/* - Get 1970's filetime. -*/ - fileTime1 = YearToFileTime(1970); - -/* - Get the current filetime time. -*/ - GetSystemTime(&sysTime); - SystemTimeToFileTime(&sysTime, &fileTime2); - - -/* - Stuff the 2 FILETIMEs into their own __int64s. -*/ - time1 = fileTime1.dwHighDateTime; - time1 <<= 32; - time1 |= fileTime1.dwLowDateTime; - - time2 = fileTime2.dwHighDateTime; - time2 <<= 32; - time2 |= fileTime2.dwLowDateTime; - -/* - Get the difference of the two64-bit ints. - - This is he number of 100-nanosecond intervals since Jan. 1970. So - we divide by 10000 to get seconds. - */ - iTimeDiff = (time2 - time1) / 10000000; - return (int)iTimeDiff; -} -#endif /* WINCE */ - -/******************************************************************************/ - - - - - -- cgit v1.2.3-54-g00ecf