]> begriffs open source - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/src/io.c
Tidy up SAM4E NetworkInterface.c.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / src / io.c
1 /* io.c
2  *
3  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
4  *
5  * This file is part of CyaSSL.
6  *
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.
11  *
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.
16  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #ifdef _WIN32_WCE
27     /* On WinCE winsock2.h must be included before windows.h for socket stuff */
28     #include <winsock2.h>
29 #endif
30
31 #include <cyassl/internal.h>
32
33 /* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
34    automatic setting of default I/O functions EmbedSend() and EmbedReceive()
35    but they'll still need SetCallback xxx() at end of file 
36 */
37 #ifndef CYASSL_USER_IO
38
39 #ifdef HAVE_LIBZ
40     #include "zlib.h"
41 #endif
42
43 #ifndef USE_WINDOWS_API
44     #ifdef CYASSL_LWIP
45         /* lwIP needs to be configured to use sockets API in this mode */
46         /* LWIP_SOCKET 1 && LWIP_COMPAT_SOCKETS 1 in lwip/opt.h or in build */
47         #define LWIP_PROVIDE_ERRNO 1
48         #include "sockets.h"
49     #else
50         #include <sys/types.h>
51         #include <errno.h>
52         #include <unistd.h>
53         #include <fcntl.h>
54         #if !(defined(DEVKITPRO) || defined(THREADX))
55             #include <sys/socket.h>
56             #include <arpa/inet.h>
57             #include <netinet/in.h>
58             #include <netdb.h>
59             #ifdef __PPU
60                 #include <netex/errno.h>
61             #else
62                 #include <sys/ioctl.h>
63             #endif
64         #endif
65         #ifdef THREADX
66             #include <socket.h>
67         #endif
68     #endif
69 #endif /* USE_WINDOWS_API */
70
71 #ifdef __sun
72     #include <sys/filio.h>
73 #endif
74
75 #ifdef USE_WINDOWS_API 
76     /* no epipe yet */
77     #ifndef WSAEPIPE
78         #define WSAEPIPE       -12345
79     #endif
80     #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
81     #define SOCKET_EAGAIN      WSAEWOULDBLOCK
82     #define SOCKET_ECONNRESET  WSAECONNRESET
83     #define SOCKET_EINTR       WSAEINTR
84     #define SOCKET_EPIPE       WSAEPIPE
85 #elif defined(__PPU)
86     #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
87     #define SOCKET_EAGAIN      SYS_NET_EAGAIN
88     #define SOCKET_ECONNRESET  SYS_NET_ECONNRESET
89     #define SOCKET_EINTR       SYS_NET_EINTR
90     #define SOCKET_EPIPE       SYS_NET_EPIPE
91 #else
92     #define SOCKET_EWOULDBLOCK EWOULDBLOCK
93     #define SOCKET_EAGAIN      EAGAIN
94     #define SOCKET_ECONNRESET  ECONNRESET
95     #define SOCKET_EINTR       EINTR
96     #define SOCKET_EPIPE       EPIPE
97 #endif /* USE_WINDOWS_API */
98
99
100 #ifdef DEVKITPRO
101     /* from network.h */
102     int net_send(int, const void*, int, unsigned int);
103     int net_recv(int, void*, int, unsigned int);
104     #define SEND_FUNCTION net_send
105     #define RECV_FUNCTION net_recv
106 #else
107     #define SEND_FUNCTION send
108     #define RECV_FUNCTION recv
109 #endif
110
111
112 static INLINE int LastError(void)
113 {
114 #ifdef USE_WINDOWS_API 
115     return WSAGetLastError();
116 #else
117     return errno;
118 #endif
119 }
120
121 /* The receive embedded callback
122  *  return : nb bytes read, or error
123  */
124 int EmbedReceive(char *buf, int sz, void *ctx)
125 {
126     int recvd;
127     int err;
128     int sd = *(int*)ctx;
129
130     recvd = RECV_FUNCTION(sd, (char *)buf, sz, 0);
131
132     if (recvd < 0) {
133         err = LastError();
134         CYASSL_MSG("Embed Receive error");
135
136         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
137             CYASSL_MSG("    Would block");
138             return IO_ERR_WANT_READ;
139         }
140         else if (err == SOCKET_ECONNRESET) {
141             CYASSL_MSG("    Connection reset");
142             return IO_ERR_CONN_RST;
143         }
144         else if (err == SOCKET_EINTR) {
145             CYASSL_MSG("    Socket interrupted");
146             return IO_ERR_ISR;
147         }
148         else {
149             CYASSL_MSG("    General error");
150             return IO_ERR_GENERAL;
151         }
152     }
153     else if (recvd == 0) {
154         CYASSL_MSG("Embed receive connection closed");
155         return IO_ERR_CONN_CLOSE;
156     }
157
158     return recvd;
159 }
160
161 /* The send embedded callback
162  *  return : nb bytes sent, or error
163  */
164 int EmbedSend(char *buf, int sz, void *ctx)
165 {
166     int sd = *(int*)ctx;
167     int sent;
168     int len = sz;
169     int err;
170
171     sent = SEND_FUNCTION(sd, &buf[sz - len], len, 0);
172
173     if (sent < 0) {
174         err = LastError();
175         CYASSL_MSG("Embed Send error");
176
177         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
178             CYASSL_MSG("    Would Block");
179             return IO_ERR_WANT_WRITE;
180         }
181         else if (err == SOCKET_ECONNRESET) {
182             CYASSL_MSG("    Connection reset");
183             return IO_ERR_CONN_RST;
184         }
185         else if (err == SOCKET_EINTR) {
186             CYASSL_MSG("    Socket interrupted");
187             return IO_ERR_ISR;
188         }
189         else if (err == SOCKET_EPIPE) {
190             CYASSL_MSG("    Socket EPIPE");
191             return IO_ERR_CONN_CLOSE;
192         }
193         else {
194             CYASSL_MSG("    General error");
195             return IO_ERR_GENERAL;
196         }
197     }
198  
199     return sent;
200 }
201
202
203 #ifdef CYASSL_DTLS
204
205 #include <cyassl/ctaocrypt/sha.h>
206
207 /* The DTLS Generate Cookie callback
208  *  return : number of bytes copied into buf, or error
209  */
210 int EmbedGenerateCookie(byte *buf, int sz, void *ctx)
211 {
212     CYASSL* ssl = (CYASSL*)ctx;
213     int sd = ssl->wfd;
214     struct sockaddr_storage peer;
215     socklen_t peerSz = sizeof(peer);
216     byte cookieSrc[sizeof(struct in6_addr) + sizeof(int)];
217     int cookieSrcSz = 0;
218     Sha sha;
219
220     getpeername(sd, (struct sockaddr*)&peer, &peerSz);
221     
222     if (peer.ss_family == AF_INET) {
223         struct sockaddr_in *s = (struct sockaddr_in*)&peer;
224
225         cookieSrcSz = sizeof(struct in_addr) + sizeof(s->sin_port);
226         XMEMCPY(cookieSrc, &s->sin_port, sizeof(s->sin_port));
227         XMEMCPY(cookieSrc + sizeof(s->sin_port),
228                                      &s->sin_addr, sizeof(struct in_addr));
229     }
230     else if (peer.ss_family == AF_INET6) {
231         struct sockaddr_in6 *s = (struct sockaddr_in6*)&peer;
232
233         cookieSrcSz = sizeof(struct in6_addr) + sizeof(s->sin6_port);
234         XMEMCPY(cookieSrc, &s->sin6_port, sizeof(s->sin6_port));
235         XMEMCPY(cookieSrc + sizeof(s->sin6_port),
236                                     &s->sin6_addr, sizeof(struct in6_addr));
237     }
238
239     InitSha(&sha);
240     ShaUpdate(&sha, cookieSrc, cookieSrcSz);
241     ShaFinal(&sha, buf);
242
243     return SHA_DIGEST_SIZE;
244 }
245
246 #endif /* CYASSL_DTLS */
247
248
249 #endif /* CYASSL_USER_IO */
250
251 CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv)
252 {
253     ctx->CBIORecv = CBIORecv;
254 }
255
256
257 CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend)
258 {
259     ctx->CBIOSend = CBIOSend;
260 }
261
262
263 CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx)
264 {
265         ssl->IOCB_ReadCtx = rctx;
266 }
267
268
269 CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx)
270 {
271         ssl->IOCB_WriteCtx = wctx;
272 }
273