3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <cyassl/ctaocrypt/settings.h>
29 /* On WinCE winsock2.h must be included before windows.h for socket stuff */
33 #include <cyassl/internal.h>
34 #include <cyassl/error-ssl.h>
36 /* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
37 automatic setting of default I/O functions EmbedSend() and EmbedReceive()
38 but they'll still need SetCallback xxx() at end of file
40 #ifndef CYASSL_USER_IO
46 #ifndef USE_WINDOWS_API
48 /* lwIP needs to be configured to use sockets API in this mode */
49 /* LWIP_SOCKET 1 in lwip/opt.h or in build */
50 #include "lwip/sockets.h"
52 #ifndef LWIP_PROVIDE_ERRNO
53 #define LWIP_PROVIDE_ERRNO 1
55 #elif defined(FREESCALE_MQX)
58 #elif defined(CYASSL_MDK_ARM)
59 #if defined(CYASSL_MDK5)
67 #include "CYASSL_MDK_ARM.h"
69 #define RNG CyaSSL_RNG
70 /* for avoiding name conflict in "stm32f2xx.h" */
72 #elif defined(CYASSL_IAR_ARM)
75 #include <sys/types.h>
81 #if !(defined(DEVKITPRO) || defined(HAVE_RTP_SYS) || defined(EBSNET))
82 #include <sys/socket.h>
83 #include <arpa/inet.h>
84 #include <netinet/in.h>
87 #include <netex/errno.h>
89 #include <sys/ioctl.h>
96 #include "rtipapi.h" /* errno */
100 #endif /* USE_WINDOWS_API */
103 #include <sys/filio.h>
106 #ifdef USE_WINDOWS_API
109 #define WSAEPIPE -12345
111 #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
112 #define SOCKET_EAGAIN WSAETIMEDOUT
113 #define SOCKET_ECONNRESET WSAECONNRESET
114 #define SOCKET_EINTR WSAEINTR
115 #define SOCKET_EPIPE WSAEPIPE
116 #define SOCKET_ECONNREFUSED WSAENOTCONN
117 #define SOCKET_ECONNABORTED WSAECONNABORTED
118 #define close(s) closesocket(s)
120 #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
121 #define SOCKET_EAGAIN SYS_NET_EAGAIN
122 #define SOCKET_ECONNRESET SYS_NET_ECONNRESET
123 #define SOCKET_EINTR SYS_NET_EINTR
124 #define SOCKET_EPIPE SYS_NET_EPIPE
125 #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED
126 #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED
127 #elif defined(FREESCALE_MQX)
128 /* RTCS doesn't have an EWOULDBLOCK error */
129 #define SOCKET_EWOULDBLOCK EAGAIN
130 #define SOCKET_EAGAIN EAGAIN
131 #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET
132 #define SOCKET_EINTR EINTR
133 #define SOCKET_EPIPE EPIPE
134 #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED
135 #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED
136 #elif defined(CYASSL_MDK_ARM)
137 #if defined(CYASSL_MDK5)
138 #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK
139 #define SOCKET_EAGAIN BSD_ERROR_LOCKED
140 #define SOCKET_ECONNRESET BSD_ERROR_CLOSED
141 #define SOCKET_EINTR BSD_ERROR
142 #define SOCKET_EPIPE BSD_ERROR
143 #define SOCKET_ECONNREFUSED BSD_ERROR
144 #define SOCKET_ECONNABORTED BSD_ERROR
146 #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK
147 #define SOCKET_EAGAIN SCK_ELOCKED
148 #define SOCKET_ECONNRESET SCK_ECLOSED
149 #define SOCKET_EINTR SCK_ERROR
150 #define SOCKET_EPIPE SCK_ERROR
151 #define SOCKET_ECONNREFUSED SCK_ERROR
152 #define SOCKET_ECONNABORTED SCK_ERROR
155 #define SOCKET_EWOULDBLOCK EWOULDBLOCK
156 #define SOCKET_EAGAIN EAGAIN
157 #define SOCKET_ECONNRESET ECONNRESET
158 #define SOCKET_EINTR EINTR
159 #define SOCKET_EPIPE EPIPE
160 #define SOCKET_ECONNREFUSED ECONNREFUSED
161 #define SOCKET_ECONNABORTED ECONNABORTED
162 #endif /* USE_WINDOWS_API */
167 int net_send(int, const void*, int, unsigned int);
168 int net_recv(int, void*, int, unsigned int);
169 #define SEND_FUNCTION net_send
170 #define RECV_FUNCTION net_recv
171 #elif defined(CYASSL_LWIP)
172 #define SEND_FUNCTION lwip_send
173 #define RECV_FUNCTION lwip_recv
175 #define SEND_FUNCTION send
176 #define RECV_FUNCTION recv
180 /* Translates return codes returned from
181 * send() and recv() if need be.
183 static INLINE int TranslateReturnCode(int old, int sd)
189 errno = SOCKET_EWOULDBLOCK;
190 return -1; /* convert to BSD style wouldblock as error */
194 errno = RTCS_geterror(sd);
195 if (errno == RTCSERR_TCP_CONN_CLOSING)
196 return 0; /* convert to BSD style closing */
203 static INLINE int LastError(void)
205 #ifdef USE_WINDOWS_API
206 return WSAGetLastError();
207 #elif defined(EBSNET)
208 return xn_getlasterror();
214 /* The receive embedded callback
215 * return : nb bytes read, or error
217 int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx)
225 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl);
227 && !CyaSSL_get_using_nonblock(ssl)
228 && dtls_timeout != 0) {
229 #ifdef USE_WINDOWS_API
230 DWORD timeout = dtls_timeout * 1000;
232 struct timeval timeout;
233 XMEMSET(&timeout, 0, sizeof(timeout));
234 timeout.tv_sec = dtls_timeout;
236 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
237 sizeof(timeout)) != 0) {
238 CYASSL_MSG("setsockopt rcvtimeo failed");
244 recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags);
246 recvd = TranslateReturnCode(recvd, sd);
250 CYASSL_MSG("Embed Receive error");
252 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
253 if (!CyaSSL_dtls(ssl) || CyaSSL_get_using_nonblock(ssl)) {
254 CYASSL_MSG(" Would block");
255 return CYASSL_CBIO_ERR_WANT_READ;
258 CYASSL_MSG(" Socket timeout");
259 return CYASSL_CBIO_ERR_TIMEOUT;
262 else if (err == SOCKET_ECONNRESET) {
263 CYASSL_MSG(" Connection reset");
264 return CYASSL_CBIO_ERR_CONN_RST;
266 else if (err == SOCKET_EINTR) {
267 CYASSL_MSG(" Socket interrupted");
268 return CYASSL_CBIO_ERR_ISR;
270 else if (err == SOCKET_ECONNREFUSED) {
271 CYASSL_MSG(" Connection refused");
272 return CYASSL_CBIO_ERR_WANT_READ;
274 else if (err == SOCKET_ECONNABORTED) {
275 CYASSL_MSG(" Connection aborted");
276 return CYASSL_CBIO_ERR_CONN_CLOSE;
279 CYASSL_MSG(" General error");
280 return CYASSL_CBIO_ERR_GENERAL;
283 else if (recvd == 0) {
284 CYASSL_MSG("Embed receive connection closed");
285 return CYASSL_CBIO_ERR_CONN_CLOSE;
291 /* The send embedded callback
292 * return : nb bytes sent, or error
294 int EmbedSend(CYASSL* ssl, char *buf, int sz, void *ctx)
301 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags);
305 CYASSL_MSG("Embed Send error");
307 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
308 CYASSL_MSG(" Would Block");
309 return CYASSL_CBIO_ERR_WANT_WRITE;
311 else if (err == SOCKET_ECONNRESET) {
312 CYASSL_MSG(" Connection reset");
313 return CYASSL_CBIO_ERR_CONN_RST;
315 else if (err == SOCKET_EINTR) {
316 CYASSL_MSG(" Socket interrupted");
317 return CYASSL_CBIO_ERR_ISR;
319 else if (err == SOCKET_EPIPE) {
320 CYASSL_MSG(" Socket EPIPE");
321 return CYASSL_CBIO_ERR_CONN_CLOSE;
324 CYASSL_MSG(" General error");
325 return CYASSL_CBIO_ERR_GENERAL;
335 #include <cyassl/ctaocrypt/sha.h>
337 #ifdef USE_WINDOWS_API
338 #define XSOCKLENT int
340 #define XSOCKLENT socklen_t
343 #define SENDTO_FUNCTION sendto
344 #define RECVFROM_FUNCTION recvfrom
347 /* The receive embedded callback
348 * return : nb bytes read, or error
350 int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx)
352 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
355 int sd = dtlsCtx->fd;
356 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl);
357 struct sockaddr_storage peer;
358 XSOCKLENT peerSz = sizeof(peer);
360 CYASSL_ENTER("EmbedReceiveFrom()");
362 if (!CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) {
363 #ifdef USE_WINDOWS_API
364 DWORD timeout = dtls_timeout * 1000;
366 struct timeval timeout;
367 XMEMSET(&timeout, 0, sizeof(timeout));
368 timeout.tv_sec = dtls_timeout;
370 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
371 sizeof(timeout)) != 0) {
372 CYASSL_MSG("setsockopt rcvtimeo failed");
376 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
377 (struct sockaddr*)&peer, &peerSz);
379 recvd = TranslateReturnCode(recvd, sd);
383 CYASSL_MSG("Embed Receive From error");
385 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
386 if (CyaSSL_get_using_nonblock(ssl)) {
387 CYASSL_MSG(" Would block");
388 return CYASSL_CBIO_ERR_WANT_READ;
391 CYASSL_MSG(" Socket timeout");
392 return CYASSL_CBIO_ERR_TIMEOUT;
395 else if (err == SOCKET_ECONNRESET) {
396 CYASSL_MSG(" Connection reset");
397 return CYASSL_CBIO_ERR_CONN_RST;
399 else if (err == SOCKET_EINTR) {
400 CYASSL_MSG(" Socket interrupted");
401 return CYASSL_CBIO_ERR_ISR;
403 else if (err == SOCKET_ECONNREFUSED) {
404 CYASSL_MSG(" Connection refused");
405 return CYASSL_CBIO_ERR_WANT_READ;
408 CYASSL_MSG(" General error");
409 return CYASSL_CBIO_ERR_GENERAL;
413 if (dtlsCtx->peer.sz > 0
414 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
415 && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
416 CYASSL_MSG(" Ignored packet from invalid peer");
417 return CYASSL_CBIO_ERR_WANT_READ;
425 /* The send embedded callback
426 * return : nb bytes sent, or error
428 int EmbedSendTo(CYASSL* ssl, char *buf, int sz, void *ctx)
430 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
431 int sd = dtlsCtx->fd;
436 CYASSL_ENTER("EmbedSendTo()");
438 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
439 dtlsCtx->peer.sa, dtlsCtx->peer.sz);
442 CYASSL_MSG("Embed Send To error");
444 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
445 CYASSL_MSG(" Would Block");
446 return CYASSL_CBIO_ERR_WANT_WRITE;
448 else if (err == SOCKET_ECONNRESET) {
449 CYASSL_MSG(" Connection reset");
450 return CYASSL_CBIO_ERR_CONN_RST;
452 else if (err == SOCKET_EINTR) {
453 CYASSL_MSG(" Socket interrupted");
454 return CYASSL_CBIO_ERR_ISR;
456 else if (err == SOCKET_EPIPE) {
457 CYASSL_MSG(" Socket EPIPE");
458 return CYASSL_CBIO_ERR_CONN_CLOSE;
461 CYASSL_MSG(" General error");
462 return CYASSL_CBIO_ERR_GENERAL;
470 /* The DTLS Generate Cookie callback
471 * return : number of bytes copied into buf, or error
473 int EmbedGenerateCookie(CYASSL* ssl, byte *buf, int sz, void *ctx)
476 struct sockaddr_storage peer;
477 XSOCKLENT peerSz = sizeof(peer);
479 byte digest[SHA_DIGEST_SIZE];
484 XMEMSET(&peer, 0, sizeof(peer));
485 if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) {
486 CYASSL_MSG("getpeername failed in EmbedGenerateCookie");
493 ShaUpdate(&sha, (byte*)&peer, peerSz);
494 ShaFinal(&sha, digest);
496 if (sz > SHA_DIGEST_SIZE)
497 sz = SHA_DIGEST_SIZE;
498 XMEMCPY(buf, digest, sz);
503 #endif /* CYASSL_DTLS */
508 static int Word16ToString(char* d, word16 number)
513 word16 order = 10000;
521 digit = number / order;
522 if (i > 0 || digit != 0) {
523 d[i++] = digit + '0';
526 number %= digit * order;
540 static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
542 struct sockaddr_storage addr;
543 int sockaddr_len = sizeof(struct sockaddr_in);
544 XMEMSET(&addr, 0, sizeof(addr));
546 #ifdef HAVE_GETADDRINFO
548 struct addrinfo hints;
549 struct addrinfo* answer = NULL;
552 XMEMSET(&hints, 0, sizeof(hints));
553 hints.ai_family = AF_UNSPEC;
554 hints.ai_socktype = SOCK_STREAM;
555 hints.ai_protocol = IPPROTO_TCP;
557 if (Word16ToString(strPort, port) == 0) {
558 CYASSL_MSG("invalid port number for OCSP responder");
562 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
563 CYASSL_MSG("no addr info for OCSP responder");
567 sockaddr_len = answer->ai_addrlen;
568 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
569 freeaddrinfo(answer);
572 #else /* HAVE_GETADDRINFO */
574 struct hostent* entry = gethostbyname(ip);
575 struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
578 sin->sin_family = AF_INET;
579 sin->sin_port = htons(port);
580 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
584 CYASSL_MSG("no addr info for OCSP responder");
588 #endif /* HAVE_GETADDRINFO */
590 *sockfd = socket(addr.ss_family, SOCK_STREAM, 0);
592 CYASSL_MSG("bad socket fd, out of fds?");
596 if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) {
597 CYASSL_MSG("OCSP responder tcp connect failed");
605 static int build_http_request(const char* domainName, const char* path,
606 int ocspReqSz, byte* buf, int bufSize)
608 word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen;
609 char ocspReqSzStr[6];
611 domainNameLen = (word32)XSTRLEN(domainName);
612 pathLen = (word32)XSTRLEN(path);
613 ocspReqSzStrLen = Word16ToString(ocspReqSzStr, ocspReqSz);
615 completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84;
616 if (completeLen > (word32)bufSize)
619 XSTRNCPY((char*)buf, "POST ", 5);
621 XSTRNCPY((char*)buf, path, pathLen);
623 XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17);
625 XSTRNCPY((char*)buf, domainName, domainNameLen);
626 buf += domainNameLen;
627 XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18);
629 XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen);
630 buf += ocspReqSzStrLen;
632 "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44);
638 static int decode_url(const char* url, int urlSz,
639 char* outName, char* outPath, word16* outPort)
643 if (outName != NULL && outPath != NULL && outPort != NULL)
645 if (url == NULL || urlSz == 0)
655 /* need to break the url down into scheme, address, and port */
656 /* "http://example.com:8080/" */
657 /* "http://[::1]:443/" */
658 if (XSTRNCMP(url, "http://", 7) == 0) {
663 if (url[cur] == '[') {
666 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
667 outName[i++] = url[cur++];
669 cur++; /* skip ']' */
672 while (url[cur] != 0 && url[cur] != ':' &&
673 url[cur] != '/' && cur < urlSz) {
674 outName[i++] = url[cur++];
678 /* Need to pick out the path after the domain name */
680 if (cur < urlSz && url[cur] == ':') {
686 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
688 port[i++] = url[cur++];
691 for (j = 0; j < i; j++) {
692 if (port[j] < '0' || port[j] > '9') return -1;
693 bigPort = (bigPort * 10) + (port[j] - '0');
695 *outPort = (word16)bigPort;
700 if (cur < urlSz && url[cur] == '/') {
702 while (cur < urlSz && url[cur] != 0 && i < 80) {
703 outPath[i++] = url[cur++];
719 /* return: >0 OCSP Response Size
721 static int process_http_response(int sfd, byte** respBuf,
722 byte* httpBuf, int httpBufSz)
727 byte *recvBuf = NULL;
729 enum phr_state { phr_init, phr_http_start, phr_have_length,
730 phr_have_type, phr_wait_end, phr_http_end
736 result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
739 start = (char*)httpBuf;
743 CYASSL_MSG("process_http_response recv http from peer failed");
747 end = XSTRSTR(start, "\r\n");
751 XMEMMOVE(httpBuf, start, len);
754 else if (end == start) {
755 if (state == phr_wait_end) {
756 state = phr_http_end;
761 CYASSL_MSG("process_http_response header ended early");
767 len -= (int)(end - start) + 2;
768 /* adjust len to remove the first line including the /r/n */
770 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
772 if (XSTRNCASECMP(start, "200 OK", 6) != 0 ||
774 CYASSL_MSG("process_http_response not OK");
777 state = phr_http_start;
779 else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
781 while (*start == ' ' && *start != '\0') start++;
782 if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) {
783 CYASSL_MSG("process_http_response not ocsp-response");
787 if (state == phr_http_start) state = phr_have_type;
788 else if (state == phr_have_length) state = phr_wait_end;
790 CYASSL_MSG("process_http_response type invalid state");
794 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
796 while (*start == ' ' && *start != '\0') start++;
797 recvBufSz = atoi(start);
799 if (state == phr_http_start) state = phr_have_length;
800 else if (state == phr_have_type) state = phr_wait_end;
802 CYASSL_MSG("process_http_response length invalid state");
809 } while (state != phr_http_end);
811 recvBuf = XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
812 if (recvBuf == NULL) {
813 CYASSL_MSG("process_http_response couldn't create response buffer");
817 /* copy the remainder of the httpBuf into the respBuf */
819 XMEMCPY(recvBuf, start, len);
821 /* receive the OCSP response data */
823 result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0);
827 CYASSL_MSG("process_http_response recv ocsp from peer failed");
830 } while (len != recvBufSz);
837 #define SCRATCH_BUFFER_SIZE 512
839 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
840 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
842 char domainName[80], path[80];
847 byte* httpBuf = NULL;
851 if (ocspReqBuf == NULL || ocspReqSz == 0) {
852 CYASSL_MSG("OCSP request is required for lookup");
856 if (ocspRespBuf == NULL) {
857 CYASSL_MSG("Cannot save OCSP response");
861 if (decode_url(url, urlSz, domainName, path, &port) < 0) {
862 CYASSL_MSG("Unable to decode OCSP URL");
866 /* Note, the library uses the EmbedOcspRespFree() callback to
867 * free this buffer. */
868 httpBufSz = SCRATCH_BUFFER_SIZE;
869 httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
871 if (httpBuf == NULL) {
872 CYASSL_MSG("Unable to create OCSP response buffer");
876 httpBufSz = build_http_request(domainName, path, ocspReqSz,
879 if ((tcp_connect(&sfd, domainName, port) == 0) && (sfd > 0)) {
881 written = (int)send(sfd, (char*)httpBuf, httpBufSz, 0);
882 if (written == httpBufSz) {
883 written = (int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0);
884 if (written == ocspReqSz) {
885 ocspRespSz = process_http_response(sfd, ocspRespBuf,
886 httpBuf, SCRATCH_BUFFER_SIZE);
890 if (ocspRespSz == 0) {
891 CYASSL_MSG("OCSP response was not OK, no OCSP response");
892 XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
896 CYASSL_MSG("OCSP Responder connection failed");
898 XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
902 XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
907 void EmbedOcspRespFree(void* ctx, byte *resp)
912 XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER);
918 #endif /* CYASSL_USER_IO */
920 CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv)
922 ctx->CBIORecv = CBIORecv;
926 CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend)
928 ctx->CBIOSend = CBIOSend;
932 CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx)
934 ssl->IOCB_ReadCtx = rctx;
938 CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx)
940 ssl->IOCB_WriteCtx = wctx;
944 CYASSL_API void* CyaSSL_GetIOReadCtx(CYASSL* ssl)
947 return ssl->IOCB_ReadCtx;
953 CYASSL_API void* CyaSSL_GetIOWriteCtx(CYASSL* ssl)
956 return ssl->IOCB_WriteCtx;
962 CYASSL_API void CyaSSL_SetIOReadFlags(CYASSL* ssl, int flags)
968 CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags)
976 CYASSL_API void CyaSSL_CTX_SetGenCookie(CYASSL_CTX* ctx, CallbackGenCookie cb)
978 ctx->CBIOCookie = cb;
982 CYASSL_API void CyaSSL_SetCookieCtx(CYASSL* ssl, void *ctx)
984 ssl->IOCB_CookieCtx = ctx;
988 CYASSL_API void* CyaSSL_GetCookieCtx(CYASSL* ssl)
991 return ssl->IOCB_CookieCtx;
996 #endif /* CYASSL_DTLS */
1001 /* The NetX receive callback
1002 * return : bytes read, or error
1004 int NetX_Receive(CYASSL *ssl, char *buf, int sz, void *ctx)
1006 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1012 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1013 CYASSL_MSG("NetX Recv NULL parameters");
1014 return CYASSL_CBIO_ERR_GENERAL;
1017 if (nxCtx->nxPacket == NULL) {
1018 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1020 if (status != NX_SUCCESS) {
1021 CYASSL_MSG("NetX Recv receive error");
1022 return CYASSL_CBIO_ERR_GENERAL;
1026 if (nxCtx->nxPacket) {
1027 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1028 if (status != NX_SUCCESS) {
1029 CYASSL_MSG("NetX Recv length get error");
1030 return CYASSL_CBIO_ERR_GENERAL;
1033 left = total - nxCtx->nxOffset;
1034 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1036 if (status != NX_SUCCESS) {
1037 CYASSL_MSG("NetX Recv data extract offset error");
1038 return CYASSL_CBIO_ERR_GENERAL;
1041 nxCtx->nxOffset += copied;
1043 if (copied == left) {
1044 CYASSL_MSG("NetX Recv Drained packet");
1045 nx_packet_release(nxCtx->nxPacket);
1046 nxCtx->nxPacket = NULL;
1047 nxCtx->nxOffset = 0;
1055 /* The NetX send callback
1056 * return : bytes sent, or error
1058 int NetX_Send(CYASSL* ssl, char *buf, int sz, void *ctx)
1060 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1062 NX_PACKET_POOL* pool; /* shorthand */
1065 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1066 CYASSL_MSG("NetX Send NULL parameters");
1067 return CYASSL_CBIO_ERR_GENERAL;
1070 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1071 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1073 if (status != NX_SUCCESS) {
1074 CYASSL_MSG("NetX Send packet alloc error");
1075 return CYASSL_CBIO_ERR_GENERAL;
1078 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1079 if (status != NX_SUCCESS) {
1080 nx_packet_release(packet);
1081 CYASSL_MSG("NetX Send data append error");
1082 return CYASSL_CBIO_ERR_GENERAL;
1085 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1086 if (status != NX_SUCCESS) {
1087 nx_packet_release(packet);
1088 CYASSL_MSG("NetX Send socket send error");
1089 return CYASSL_CBIO_ERR_GENERAL;
1096 /* like set_fd, but for default NetX context */
1097 void CyaSSL_SetIO_NetX(CYASSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1100 ssl->nxCtx.nxSocket = nxSocket;
1101 ssl->nxCtx.nxWait = waitOption;
1105 #endif /* HAVE_NETX */