1 /*============================================================================
2 socket.c
3 ==============================================================================
4 Implementation of TChanSwitch class: A generic channel switch -- an object
5 that brokers a connection between an HTTP client and server.
6 ============================================================================*/
7
8 #include <sys/types.h>
9 #include <assert.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #include "bool.h"
14 #include "int.h"
15 #include "mallocvar.h"
16 #include "xmlrpc-c/util_int.h"
17 #include "xmlrpc-c/abyss.h"
18 #ifdef WIN32
19 #include "socket_win.h"
20 #else
21 #include "socket_unix.h"
22 #endif
23 #include "chanswitch.h"
24
25
26 static void
socketOsInit(const char ** const errorP)27 socketOsInit(const char ** const errorP) {
28
29 #ifdef WIN32
30 SocketWinInit(errorP);
31 #else
32 SocketUnixInit(errorP);
33 #endif
34 }
35
36
37
38 static void
socketOsTerm(void)39 socketOsTerm(void) {
40
41 #ifdef WIN32
42 SocketWinTerm();
43 #else
44 SocketUnixTerm();
45 #endif
46 }
47
48
49
50 bool SwitchTraceIsActive;
51
52 void
ChanSwitchInit(const char ** const errorP)53 ChanSwitchInit(const char ** const errorP) {
54
55 socketOsInit(errorP);
56
57 if (!*errorP) {
58 SwitchTraceIsActive = (getenv("ABYSS_TRACE_SWITCH") != NULL);
59 if (SwitchTraceIsActive)
60 fprintf(stderr, "Abyss channel switch layer will trace "
61 "channel connection activity "
62 "due to ABYSS_TRACE_SWITCH environment variable\n");
63 }
64 }
65
66
67
68 void
ChanSwitchTerm(void)69 ChanSwitchTerm(void) {
70
71 socketOsTerm();
72 }
73
74
75
76 /* ChanSwitchCreate() is not exported to the Abyss user. It is meant to
77 be used by an implementation-specific TChanSwitch generator which is
78 exported to the Abyss user, e.g. SwitchCreateUnix() in
79 socket_unix.c
80
81 The TChanSwitch generator functions are the _only_ user-accessible
82 functions that are particular to an implementation.
83 */
84
85 static unsigned int const switchSignature = 0x06060A;
86
87 void
ChanSwitchCreate(const struct TChanSwitchVtbl * const vtblP,void * const implP,TChanSwitch ** const chanSwitchPP)88 ChanSwitchCreate(const struct TChanSwitchVtbl * const vtblP,
89 void * const implP,
90 TChanSwitch ** const chanSwitchPP) {
91
92 TChanSwitch * chanSwitchP;
93
94 MALLOCVAR(chanSwitchP);
95
96 if (chanSwitchP) {
97 chanSwitchP->implP = implP;
98 chanSwitchP->vtbl = *vtblP;
99 chanSwitchP->signature = switchSignature;
100
101 if (SwitchTraceIsActive)
102 fprintf(stderr, "Created channel switch %p\n", chanSwitchP);
103
104 *chanSwitchPP = chanSwitchP;
105 }
106 }
107
108
109
110 void
ChanSwitchDestroy(TChanSwitch * const chanSwitchP)111 ChanSwitchDestroy(TChanSwitch * const chanSwitchP) {
112
113 if (SwitchTraceIsActive)
114 fprintf(stderr, "Destroying channel switch %p\n", chanSwitchP);
115
116 assert(chanSwitchP->signature == switchSignature);
117
118 chanSwitchP->vtbl.destroy(chanSwitchP);
119
120 chanSwitchP->signature = 0; /* For debuggability */
121
122 free(chanSwitchP);
123 }
124
125
126
127 void
ChanSwitchListen(TChanSwitch * const chanSwitchP,uint32_t const backlog,const char ** const errorP)128 ChanSwitchListen(TChanSwitch * const chanSwitchP,
129 uint32_t const backlog,
130 const char ** const errorP) {
131
132 if (SwitchTraceIsActive)
133 fprintf(stderr, "Channel switch %p listening.\n", chanSwitchP);
134
135 (*chanSwitchP->vtbl.listen)(chanSwitchP, backlog, errorP);
136 }
137
138
139
140 void
ChanSwitchAccept(TChanSwitch * const chanSwitchP,TChannel ** const channelPP,void ** const channelInfoPP,const char ** const errorP)141 ChanSwitchAccept(TChanSwitch * const chanSwitchP,
142 TChannel ** const channelPP,
143 void ** const channelInfoPP,
144 const char ** const errorP) {
145
146 if (SwitchTraceIsActive)
147 fprintf(stderr, "Getting a connection from Channel switch %p...\n",
148 chanSwitchP);
149
150 (*chanSwitchP->vtbl.accept)(chanSwitchP, channelPP, channelInfoPP, errorP);
151
152 if (SwitchTraceIsActive)
153 fprintf(stderr, "Got connection from channel switch. "
154 "Channel = %p\n", *channelPP);
155 }
156
157
158
159 void
ChanSwitchInterrupt(TChanSwitch * const chanSwitchP)160 ChanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
161
162 if (SwitchTraceIsActive)
163 fprintf(stderr, "Interrupting wait for a connection "
164 "by Channel switch %p...\n",
165 chanSwitchP);
166
167 (*chanSwitchP->vtbl.interrupt)(chanSwitchP);
168 }
169