]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winhsock.c
Factor out the HANDLE-to-Socket adapter from winproxy.c.
[PuTTY.git] / windows / winhsock.c
1 /*
2  * General mechanism for wrapping up reading/writing of Windows
3  * HANDLEs into a PuTTY Socket abstraction.
4  */
5
6 #include <stdio.h>
7 #include <assert.h>
8
9 #define DEFINE_PLUG_METHOD_MACROS
10 #include "tree234.h"
11 #include "putty.h"
12 #include "network.h"
13
14 typedef struct Socket_handle_tag *Handle_Socket;
15
16 struct Socket_handle_tag {
17     const struct socket_function_table *fn;
18     /* the above variable absolutely *must* be the first in this structure */
19
20     HANDLE send_H, recv_H;
21     struct handle *send_h, *recv_h;
22
23     char *error;
24
25     Plug plug;
26
27     void *privptr;
28 };
29
30 static int handle_gotdata(struct handle *h, void *data, int len)
31 {
32     Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
33
34     if (len < 0) {
35         return plug_closing(ps->plug, "Read error from handle",
36                             0, 0);
37     } else if (len == 0) {
38         return plug_closing(ps->plug, NULL, 0, 0);
39     } else {
40         return plug_receive(ps->plug, 0, data, len);
41     }
42 }
43
44 static void handle_sentdata(struct handle *h, int new_backlog)
45 {
46     Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
47     
48     plug_sent(ps->plug, new_backlog);
49 }
50
51 static Plug sk_handle_plug(Socket s, Plug p)
52 {
53     Handle_Socket ps = (Handle_Socket) s;
54     Plug ret = ps->plug;
55     if (p)
56         ps->plug = p;
57     return ret;
58 }
59
60 static void sk_handle_close(Socket s)
61 {
62     Handle_Socket ps = (Handle_Socket) s;
63
64     handle_free(ps->send_h);
65     handle_free(ps->recv_h);
66     CloseHandle(ps->send_H);
67     if (ps->recv_H != ps->send_H)
68         CloseHandle(ps->recv_H);
69
70     sfree(ps);
71 }
72
73 static int sk_handle_write(Socket s, const char *data, int len)
74 {
75     Handle_Socket ps = (Handle_Socket) s;
76
77     return handle_write(ps->send_h, data, len);
78 }
79
80 static int sk_handle_write_oob(Socket s, const char *data, int len)
81 {
82     /*
83      * oob data is treated as inband; nasty, but nothing really
84      * better we can do
85      */
86     return sk_handle_write(s, data, len);
87 }
88
89 static void sk_handle_write_eof(Socket s)
90 {
91     Handle_Socket ps = (Handle_Socket) s;
92
93     handle_write_eof(ps->send_h);
94 }
95
96 static void sk_handle_flush(Socket s)
97 {
98     /* Handle_Socket ps = (Handle_Socket) s; */
99     /* do nothing */
100 }
101
102 static void sk_handle_set_private_ptr(Socket s, void *ptr)
103 {
104     Handle_Socket ps = (Handle_Socket) s;
105     ps->privptr = ptr;
106 }
107
108 static void *sk_handle_get_private_ptr(Socket s)
109 {
110     Handle_Socket ps = (Handle_Socket) s;
111     return ps->privptr;
112 }
113
114 static void sk_handle_set_frozen(Socket s, int is_frozen)
115 {
116     Handle_Socket ps = (Handle_Socket) s;
117
118     /*
119      * FIXME
120      */
121 }
122
123 static const char *sk_handle_socket_error(Socket s)
124 {
125     Handle_Socket ps = (Handle_Socket) s;
126     return ps->error;
127 }
128
129 Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug,
130                           int overlapped)
131 {
132     static const struct socket_function_table socket_fn_table = {
133         sk_handle_plug,
134         sk_handle_close,
135         sk_handle_write,
136         sk_handle_write_oob,
137         sk_handle_write_eof,
138         sk_handle_flush,
139         sk_handle_set_private_ptr,
140         sk_handle_get_private_ptr,
141         sk_handle_set_frozen,
142         sk_handle_socket_error
143     };
144
145     Handle_Socket ret;
146     int flags = (overlapped ? HANDLE_FLAG_OVERLAPPED : 0);
147
148     ret = snew(struct Socket_handle_tag);
149     ret->fn = &socket_fn_table;
150     ret->plug = plug;
151     ret->error = NULL;
152
153     ret->recv_H = recv_H;
154     ret->recv_h = handle_input_new(ret->recv_H, handle_gotdata, ret, flags);
155     ret->send_H = send_H;
156     ret->send_h = handle_output_new(ret->send_H, handle_sentdata, ret, flags);
157
158     return (Socket) ret;
159 }