1/*
2 * "Default" SSLSocket methods, used by sockets that do neither SSL nor socks.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8#include "cert.h"
9#include "ssl.h"
10#include "sslimpl.h"
11
12#if defined(WIN32)
13#define MAP_ERROR(from,to) if (err == from) { PORT_SetError(to); }
14#define DEFINE_ERROR       PRErrorCode err = PR_GetError();
15#else
16#define MAP_ERROR(from,to)
17#define DEFINE_ERROR
18#endif
19
20int ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
21{
22    PRFileDesc *lower = ss->fd->lower;
23    int rv;
24
25    rv = lower->methods->connect(lower, sa, ss->cTimeout);
26    return rv;
27}
28
29int ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
30{
31    PRFileDesc *lower = ss->fd->lower;
32    int rv;
33
34    rv = lower->methods->bind(lower, addr);
35    return rv;
36}
37
38int ssl_DefListen(sslSocket *ss, int backlog)
39{
40    PRFileDesc *lower = ss->fd->lower;
41    int rv;
42
43    rv = lower->methods->listen(lower, backlog);
44    return rv;
45}
46
47int ssl_DefShutdown(sslSocket *ss, int how)
48{
49    PRFileDesc *lower = ss->fd->lower;
50    int rv;
51
52    rv = lower->methods->shutdown(lower, how);
53    return rv;
54}
55
56int ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
57{
58    PRFileDesc *lower = ss->fd->lower;
59    int rv;
60
61    rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout);
62    if (rv < 0) {
63	DEFINE_ERROR
64	MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
65    } else if (rv > len) {
66	PORT_Assert(rv <= len);
67	PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
68	rv = SECFailure;
69    }
70    return rv;
71}
72
73/* Default (unencrypted) send.
74 * For blocking sockets, always returns len or SECFailure, no short writes.
75 * For non-blocking sockets:
76 *   Returns positive count if any data was written, else returns SECFailure.
77 *   Short writes may occur.  Does not return SECWouldBlock.
78 */
79int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
80{
81    PRFileDesc *lower = ss->fd->lower;
82    int sent = 0;
83
84#if NSS_DISABLE_NAGLE_DELAYS
85    /* Although this is overkill, we disable Nagle delays completely for
86    ** SSL sockets.
87    */
88    if (ss->opt.useSecurity && !ss->delayDisabled) {
89	ssl_EnableNagleDelay(ss, PR_FALSE);   /* ignore error */
90    	ss->delayDisabled = 1;
91    }
92#endif
93    do {
94	int rv = lower->methods->send(lower, (const void *)(buf + sent),
95	                              len - sent, flags, ss->wTimeout);
96	if (rv < 0) {
97	    PRErrorCode err = PR_GetError();
98	    if (err == PR_WOULD_BLOCK_ERROR) {
99		ss->lastWriteBlocked = 1;
100		return sent ? sent : SECFailure;
101	    }
102	    ss->lastWriteBlocked = 0;
103	    MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
104	    /* Loser */
105	    return rv;
106	}
107	sent += rv;
108
109	if (IS_DTLS(ss) && (len > sent)) {
110	    /* We got a partial write so just return it */
111	    return sent;
112	}
113    } while (len > sent);
114    ss->lastWriteBlocked = 0;
115    return sent;
116}
117
118int ssl_DefRead(sslSocket *ss, unsigned char *buf, int len)
119{
120    PRFileDesc *lower = ss->fd->lower;
121    int rv;
122
123    rv = lower->methods->read(lower, (void *)buf, len);
124    if (rv < 0) {
125	DEFINE_ERROR
126	MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
127    }
128    return rv;
129}
130
131int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
132{
133    PRFileDesc *lower = ss->fd->lower;
134    int sent = 0;
135
136    do {
137	int rv = lower->methods->write(lower, (const void *)(buf + sent),
138	                               len - sent);
139	if (rv < 0) {
140	    PRErrorCode err = PR_GetError();
141	    if (err == PR_WOULD_BLOCK_ERROR) {
142		ss->lastWriteBlocked = 1;
143		return sent ? sent : SECFailure;
144	    }
145	    ss->lastWriteBlocked = 0;
146	    MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
147	    /* Loser */
148	    return rv;
149	}
150	sent += rv;
151    } while (len > sent);
152    ss->lastWriteBlocked = 0;
153    return sent;
154}
155
156int ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
157{
158    PRFileDesc *lower = ss->fd->lower;
159    int rv;
160
161    rv = lower->methods->getpeername(lower, name);
162    return rv;
163}
164
165int ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
166{
167    PRFileDesc *lower = ss->fd->lower;
168    int rv;
169
170    rv = lower->methods->getsockname(lower, name);
171    return rv;
172}
173
174int ssl_DefClose(sslSocket *ss)
175{
176    PRFileDesc *fd;
177    PRFileDesc *popped;
178    int         rv;
179
180    fd    = ss->fd;
181
182    /* First, remove the SSL layer PRFileDesc from the socket's stack,
183    ** then invoke the SSL layer's PRFileDesc destructor.
184    ** This must happen before the next layer down is closed.
185    */
186    PORT_Assert(fd->higher == NULL);
187    if (fd->higher) {
188	PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
189	return SECFailure;
190    }
191    ss->fd = NULL;
192
193    /* PR_PopIOLayer will swap the contents of the top two PRFileDescs on
194    ** the stack, and then remove the second one.  This way, the address
195    ** of the PRFileDesc on the top of the stack doesn't change.
196    */
197    popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
198    popped->dtor(popped);
199
200    /* fd is now the PRFileDesc for the next layer down.
201    ** Now close the underlying socket.
202    */
203    rv = fd->methods->close(fd);
204
205    ssl_FreeSocket(ss);
206
207    SSL_TRC(5, ("%d: SSL[%d]: closing, rv=%d errno=%d",
208		SSL_GETPID(), fd, rv, PORT_GetError()));
209    return rv;
210}
211