summaryrefslogtreecommitdiff
path: root/release/src/router/cyassl/src/cyassl_io.c
blob: a5f5283f8a50c1059c41d1c2673badc6f3bd6d73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* cyassl_io.c
 *
 * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
 *
 * This file is part of CyaSSL.
 *
 * CyaSSL is free software; 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.
 *
 * CyaSSL is distributed in the hope that it will be useful,
 * but 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
 */


#ifdef _WIN32_WCE
    /* On WinCE winsock2.h must be included before windows.h for socket stuff */
    #include <winsock2.h>
#endif

#include "cyassl_int.h"

/* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
   automatic setting of default I/O functions EmbedSend() and EmbedReceive()
   but they'll still nedd SetCallback xxx() at end of file 
*/
#ifndef CYASSL_USER_IO

#ifdef HAVE_LIBZ
    #include "zlib.h"
#endif

#ifndef USE_WINDOWS_API 
    #include <sys/types.h>
    #include <errno.h>
    #include <unistd.h>
    #include <fcntl.h>
    #if !(defined(DEVKITPRO) || defined(THREADX))
        #include <sys/socket.h>
        #include <arpa/inet.h>
        #include <netinet/in.h>
        #include <netdb.h>
        #include <sys/ioctl.h>
    #endif
    #ifdef THREADX
        #include <socket.h>
    #endif
#endif /* USE_WINDOWS_API */

#ifdef __sun
    #include <sys/filio.h>
#endif

#ifdef USE_WINDOWS_API 
    /* no epipe yet */
    #ifndef WSAEPIPE
        #define WSAEPIPE       -12345
    #endif
    #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
    #define SOCKET_EAGAIN      WSAEWOULDBLOCK
    #define SOCKET_ECONNRESET  WSAECONNRESET
    #define SOCKET_EINTR       WSAEINTR
    #define SOCKET_EPIPE       WSAEPIPE
#else
    #define SOCKET_EWOULDBLOCK EWOULDBLOCK
    #define SOCKET_EAGAIN      EAGAIN
    #define SOCKET_ECONNRESET  ECONNRESET
    #define SOCKET_EINTR       EINTR
    #define SOCKET_EPIPE       EPIPE
#endif /* USE_WINDOWS_API */


#ifdef DEVKITPRO
    /* from network.h */
    int net_send(int, const void*, int, unsigned int);
    int net_recv(int, void*, int, unsigned int);
    #define SEND_FUNCTION net_send
    #define RECV_FUNCTION net_recv
#else
    #define SEND_FUNCTION send
    #define RECV_FUNCTION recv
#endif


static INLINE int LastError(void)
{
#ifdef USE_WINDOWS_API 
    return WSAGetLastError();
#else
    return errno;
#endif
}

/* The receive embedded callback
 *  return : nb bytes read, or error
 */
int EmbedReceive(char *buf, int sz, void *ctx)
{
    int recvd;
    int err;
    int socket = *(int*)ctx;

    recvd = RECV_FUNCTION(socket, (char *)buf, sz, 0);

    if (recvd == -1) {
        err = LastError();
        if (err == SOCKET_EWOULDBLOCK ||
            err == SOCKET_EAGAIN)
            return IO_ERR_WANT_READ;

        else if (err == SOCKET_ECONNRESET)
            return IO_ERR_CONN_RST;

        else if (err == SOCKET_EINTR)
            return IO_ERR_ISR;

        else
            return IO_ERR_GENERAL;
    }
    else if (recvd == 0)
        return IO_ERR_CONN_CLOSE;

    return recvd;
}

/* The send embedded callback
 *  return : nb bytes sent, or error
 */
int EmbedSend(char *buf, int sz, void *ctx)
{
    int socket = *(int*)ctx;
    int sent;
    int len = sz;

    sent = SEND_FUNCTION(socket, &buf[sz - len], len, 0);

    if (sent == -1) {
        if (LastError() == SOCKET_EWOULDBLOCK || 
            LastError() == SOCKET_EAGAIN)
            return IO_ERR_WANT_WRITE;

        else if (LastError() == SOCKET_ECONNRESET)
            return IO_ERR_CONN_RST;

        else if (LastError() == SOCKET_EINTR)
            return IO_ERR_ISR;

        else if (LastError() == SOCKET_EPIPE)
            return IO_ERR_CONN_CLOSE;

        else
            return IO_ERR_GENERAL;
    }
 
    return sent;
}


#endif /* CYASSL_USER_IO */

void CyaSSL_SetIORecv(SSL_CTX *ctx, CallbackIORecv CBIORecv)
{
    ctx->CBIORecv = CBIORecv;
}


void CyaSSL_SetIOSend(SSL_CTX *ctx, CallbackIOSend CBIOSend)
{
    ctx->CBIOSend = CBIOSend;
}


void CyaSSL_SetIOReadCtx(SSL* ssl, void *rctx)
{
	ssl->IOCB_ReadCtx = rctx;
}


void CyaSSL_SetIOWriteCtx(SSL* ssl, void *wctx)
{
	ssl->IOCB_WriteCtx = wctx;
}