AmendHub

Download

julienxx

/

EasyNet

/

EasyNet.c

 

(View History)

julienxx   refact GiveTime -> Deadline/Idle Latest amendment: 8 on 2026-10-25

1 #include <stdlib.h>
2 #include <string.h>
3 #include <Events.h>
4 #include <OpenTransport.h>
5 #include <OpenTptInternet.h>
6 #include "EasyNet.h"
7
8 struct EasyNetConn {
9 EndpointRef ep;
10 UInt32 timeoutTicks;
11 };
12
13 static UInt32 Deadline(EasyNetConn *conn)
14 {
15 return TickCount() + conn->timeoutTicks;
16 }
17
18 static Boolean Idle(UInt32 deadline)
19 {
20 EventRecord event;
21
22 if(TickCount() > deadline)
23 return false;
24 WaitNextEvent(0, &event, 1, NULL);
25 return true;
26 }
27
28 OSStatus EasyNet_Init(void)
29 {
30 return InitOpenTransport();
31 }
32
33 void EasyNet_Shutdown(void)
34 {
35 CloseOpenTransport();
36 }
37
38 OSStatus EasyNet_Connect(const char *host, UInt16 port, long timeoutSecs, EasyNetConn **outConn)
39 {
40 OSStatus err;
41 InetSvcRef inetServices;
42 InetHostInfo hostInfo;
43 EasyNetConn *conn;
44 InetAddress addr;
45 TCall sndCall;
46 OTResult event;
47 UInt32 deadline;
48
49 *outConn = NULL;
50
51 /* look up host */
52 inetServices = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err);
53 if(err != noErr)
54 return err;
55 err = OTInetStringToAddress(inetServices, (char *) host, &hostInfo);
56 OTCloseProvider(inetServices);
57 if(err != noErr)
58 return err;
59
60 conn = (EasyNetConn *) malloc(sizeof(EasyNetConn));
61 if(conn == NULL)
62 return memFullErr;
63 conn->ep = kOTInvalidEndpointRef;
64 conn->timeoutTicks = timeoutSecs * 60;
65
66 /* create endpoint */
67 conn->ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL, &err);
68 if(err != noErr)
69 goto fail;
70 OTSetSynchronous(conn->ep);
71 OTSetNonBlocking(conn->ep);
72
73 err = OTBind(conn->ep, NULL, NULL);
74 if(err != noErr)
75 goto fail;
76
77 /* connect */
78 OTInitInetAddress(&addr, port, hostInfo.addrs[0]);
79 OTMemzero(&sndCall, sizeof(TCall));
80 sndCall.addr.buf = (UInt8 *) &addr;
81 sndCall.addr.len = sizeof(InetAddress);
82
83 err = OTConnect(conn->ep, &sndCall, NULL);
84 if(err == kOTLookErr)
85 err = kOTNoDataErr;
86
87 /* wait for conn */
88 deadline = Deadline(conn);
89 while(err == kOTNoDataErr) {
90 event = OTLook(conn->ep);
91 if(event == T_CONNECT) {
92 err = OTRcvConnect(conn->ep, NULL);
93 } else if(event == T_DISCONNECT) {
94 OTRcvDisconnect(conn->ep, NULL);
95 err = kEasyNetConnectFailedErr;
96 } else if(!Idle(deadline)) {
97 err = kEasyNetTimeoutErr;
98 }
99 }
100 if(err != noErr)
101 goto fail;
102
103 *outConn = conn;
104 return noErr;
105
106 fail:
107 if(conn->ep != kOTInvalidEndpointRef)
108 OTCloseProvider(conn->ep);
109 free(conn);
110 return err;
111 }
112
113 OSStatus EasyNet_Send(EasyNetConn *conn, const void *data, long length)
114 {
115 const char *p = (const char *) data;
116 OTResult result;
117 UInt32 deadline;
118
119 deadline = Deadline(conn);
120 while(length > 0) {
121 result = OTSnd(conn->ep, (void *) p, length, 0);
122 if(result >0) {
123 p+= result;
124 length -= result;
125 deadline = Deadline(conn);
126 } else if(result == kOTFlowErr) {
127 if(!Idle(deadline))
128 return kEasyNetTimeoutErr;
129 } else if(result == kOTLookErr) {
130 return kEasyNetDisconnectedErr;
131 } else {
132 return result;
133 }
134 }
135 return noErr;
136 }
137
138 OSStatus EasyNet_SendString(EasyNetConn *conn, const char *s)
139 {
140 return EasyNet_Send(conn, s, strlen(s));
141 }
142
143 long EasyNet_Receive(EasyNetConn *conn, void *buf, long size)
144 {
145 OTResult result;
146 OTResult event;
147 OTFlags flags;
148 UInt32 deadline;
149
150 deadline = TickCount() + conn->timeoutTicks;
151 for(;;) {
152 result = OTRcv(conn->ep, buf, size, &flags);
153 if(result > 0)
154 return result;
155
156 if(result == kOTLookErr) {
157 event = OTLook(conn->ep);
158 if(event == T_ORDREL) {
159 OTRcvOrderlyDisconnect(conn->ep);
160 return 0;
161 }
162 if(event == T_DISCONNECT) {
163 OTRcvDisconnect(conn->ep, NULL);
164 return kEasyNetDisconnectedErr;
165 }
166 } else if(result != kOTNoDataErr) {
167 return result;
168 }
169
170 if(!Idle(deadline))
171 return kEasyNetTimeoutErr;
172 }
173 }
174
175 void EasyNet_Close(EasyNetConn *conn)
176 {
177 if(conn == NULL)
178 return;
179 OTSndOrderlyDisconnect(conn->ep);
180 OTCloseProvider(conn->ep);
181 free(conn);
182 }