84
84
#define CONN_NOT_NULL_EX(subcode, func_name, retval) \
87
const STimeout* timeout = 0/*dummy*/; \
87
static const STimeout* timeout = 0/*dummy*/; \
88
88
CONN_LOG_EX(subcode, func_name, eLOG_Error, \
89
89
"NULL connection handle", retval); \
93
93
if (conn->magic != CONNECTION_MAGIC) { \
94
const STimeout* timeout = 0/*dummy*/; \
94
static const STimeout* timeout = 0/*dummy*/; \
95
95
CONN_LOG_EX(subcode, func_name, eLOG_Critical, \
96
"Data corruption detected", 0); \
96
"Corrupted connection handle", 0); \
135
147
STimeout ww_timeout; /* storage for "w_timeout" */
136
148
STimeout cc_timeout; /* storage for "c_timeout" */
138
SCONN_Callback cbs[CONN_N_CALLBACKS];
150
TNCBI_BigCount r_pos; /* read and ... */
151
TNCBI_BigCount w_pos; /* ... write positions */
153
SCONN_Callback cb[CONN_N_CALLBACKS];
140
155
unsigned int magic; /* magic number for integrity checks */
144
static EIO_Status x_ReInit
150
const STimeout* timeout = 0/*dummy*/;
159
static EIO_Status x_Callback(CONN conn, ECONN_Callback type)
164
assert(conn && (int) type >= 0 && (int) type < CONN_N_CALLBACKS);
165
if (conn->state == eCONN_Unusable)
167
if (!(func = conn->cb[type].func))
169
data = conn->cb[type].data;
170
/* allow a CB only once */
171
memset(&conn->cb[type], 0, sizeof(conn->cb[type]));
172
return (*func)(conn, type, data);
176
static EIO_Status x_ReInit(CONN conn, CONNECTOR connector)
178
static const STimeout* timeout = 0/*dummy*/;
152
182
assert(conn->meta.list || conn->state == eCONN_Unusable);
154
/* reset and close current connector(s), if any */
155
if (conn->meta.list) {
156
if (conn->state == eCONN_Open) {
157
/* call current connector's "FLUSH" method */
158
if (conn->meta.flush) {
159
conn->meta.flush(conn->meta.c_flush,
160
conn->c_timeout == kDefaultTimeout
161
? conn->meta.default_timeout
184
/* Call current connector's "FLUSH" method */
185
status = conn->meta.list && conn->state == eCONN_Open && conn->meta.flush
186
? conn->meta.flush(conn->meta.c_flush,
187
conn->c_timeout == kDefaultTimeout
188
? conn->meta.default_timeout
167
192
for (x_conn = conn->meta.list; x_conn; x_conn = x_conn->next) {
168
193
if (x_conn == connector) {
169
194
/* Reinit with the same and the only connector - allowed */
170
195
if (!x_conn->next && x_conn == conn->meta.list)
172
status = eIO_Unknown;
173
CONN_LOG(4, ReInit, eLOG_Error, "Partial re-init not allowed");
197
status = eIO_NotSupported;
198
CONN_LOG(4, ReInit, eLOG_Critical, "Partial re-init not allowed");
199
conn->state = eCONN_Bad;
181
/* NB: Re-initing with same connector does not cause the callback; */
182
/* NB: Newly created connection can't have a callback set just as yet*/
183
if (conn->state != eCONN_Unusable) {
184
func = conn->cbs[eCONN_OnClose].func;
185
data = conn->cbs[eCONN_OnClose].data;
190
/* allow close CB only once */
191
memset(&conn->cbs[eCONN_OnClose], 0, sizeof(conn->cbs[eCONN_OnClose]));
194
func(conn, eCONN_OnClose, data);
197
204
if (conn->meta.list) {
198
/* erase unread data */
205
/* Erase unread data */
199
206
BUF_Erase(conn->buf);
201
if (conn->state == eCONN_Open) {
202
/* call current connector's "CLOSE" method */
209
/* NB: Re-init with same connector does not cause the callback */
210
status = x_Callback(conn, eCONN_OnClose);
213
if (conn->state & eCONN_Open) {
214
/* Call current connector's "CLOSE" method */
203
215
if (conn->meta.close) {
204
status = conn->meta.close(conn->meta.c_close,
217
closed = conn->meta.close(conn->meta.c_close,
205
218
conn->c_timeout == kDefaultTimeout
206
219
? conn->meta.default_timeout
207
220
: conn->c_timeout);
208
if (status != eIO_Success && status != eIO_Closed) {
209
CONN_LOG(3, ReInit, connector ? eLOG_Error : eLOG_Warning,
210
"Error closing connection");
212
conn->state = eCONN_Bad;
217
conn->state = eCONN_Closed;
221
if (closed != eIO_Success)
224
if (status != eIO_Success
225
&& (status != eIO_Closed || connector)) {
226
CONN_LOG(3, ReInit, connector ? eLOG_Error : eLOG_Warning,
227
"Connection failed to close properly");
276
304
***********************************************************************/
306
extern EIO_Status CONN_CreateEx
307
(CONNECTOR connector,
315
conn = (SConnection*) calloc(1, sizeof(SConnection));
318
conn->flags = flags & ~fCONN_Flush;
319
conn->state = eCONN_Unusable;
320
conn->o_timeout = kDefaultTimeout;
321
conn->r_timeout = kDefaultTimeout;
322
conn->w_timeout = kDefaultTimeout;
323
conn->c_timeout = kDefaultTimeout;
324
conn->magic = CONNECTION_MAGIC;
325
if ((status = x_ReInit(conn, connector)) != eIO_Success) {
330
status = eIO_Unknown;
332
static const STimeout* timeout = 0/*dummy*/;
334
status = eIO_InvalidArg;
335
CONN_LOG(2, Create, eLOG_Error, "NULL connector");
278
343
extern EIO_Status CONN_Create
279
344
(CONNECTOR connector,
286
return eIO_InvalidArg;
288
conn = (SConnection*) calloc(1, sizeof(SConnection));
291
conn->state = eCONN_Unusable;
292
conn->o_timeout = kDefaultTimeout;
293
conn->r_timeout = kDefaultTimeout;
294
conn->w_timeout = kDefaultTimeout;
295
conn->c_timeout = kDefaultTimeout;
296
conn->magic = CONNECTION_MAGIC;
297
if ((status = x_ReInit(conn, connector)) != eIO_Success) {
302
status = eIO_Unknown;
347
return CONN_CreateEx(connector, 0, conn);
573
646
EIO_Status status;
648
CONN_NOT_NULL(18, Write);
576
651
return eIO_InvalidArg;
578
653
if (size && !buf)
579
654
return eIO_InvalidArg;
581
CONN_NOT_NULL(18, Write);
583
if (conn->state == eCONN_Unusable)
584
return eIO_InvalidArg;
586
656
/* open connection, if not yet opened */
587
657
if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success)
589
assert(conn->state == eCONN_Open && conn->meta.list);
659
assert((conn->state & eCONN_Open) && conn->meta.list);
592
662
case eIO_WritePlain:
593
return s_CONN_Write(conn, buf, size, n_written);
663
status = s_CONN_Write(conn, buf, size, n_written);
594
665
case eIO_WritePersist:
595
666
return s_CONN_WritePersist(conn, buf, size, n_written);
667
case eIO_WriteSupplement:
668
conn->w_status = s_CONN_Write(conn, buf, size, n_written);
669
return conn->w_status;
671
return eIO_NotSupported;
674
conn->w_status = status;
675
if (conn->flags & fCONN_Supplement)
677
return *n_written ? eIO_Success : status;
626
704
CONN_NOT_NULL(20, Flush);
628
if (conn->state == eCONN_Unusable)
629
return eIO_InvalidArg;
631
706
/* perform open, if not opened yet */
632
707
if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success)
634
assert(conn->state == eCONN_Open && conn->meta.list);
709
assert((conn->state & eCONN_Open) && conn->meta.list);
636
711
/* call current connector's "FLUSH" method */
637
if (!conn->meta.flush)
639
timeout = (conn->w_timeout == kDefaultTimeout
640
? conn->meta.default_timeout
642
status = conn->meta.flush(conn->meta.c_flush, timeout);
712
if (conn->meta.flush) {
713
timeout = (conn->w_timeout == kDefaultTimeout
714
? conn->meta.default_timeout
716
status = conn->meta.flush(conn->meta.c_flush, timeout);
717
if (status != eIO_Success)
718
CONN_LOG(21, Flush, eLOG_Warning, "Failed to flush");
720
conn->flags |= fCONN_Flush;
721
conn->w_status = status;
723
status = eIO_Success;
644
if (status != eIO_Success)
645
CONN_LOG(21, Flush, eLOG_Warning, "Failed to flush");
679
761
buf = (char*) buf + *n_read;
682
/* read data from the connection */
764
if ((status = x_Callback(conn, eCONN_OnRead)) != eIO_Success)
767
/* call current connector's "READ" method */
684
769
size_t x_read = 0;
685
770
timeout = (conn->r_timeout == kDefaultTimeout
686
771
? conn->meta.default_timeout
687
772
: conn->r_timeout);
688
/* call current connector's "READ" method */
689
773
status = conn->meta.read(conn->meta.c_read, buf, size - *n_read,
690
774
&x_read, timeout);
691
775
*n_read += x_read;
693
777
/* save data in the internal peek buffer */
694
if (peek && !BUF_Write(&conn->buf, buf, x_read))
695
CONN_LOG_EX(32, Read, eLOG_Error, "Cannot save peek data", 0);
778
if (peek && !BUF_Write(&conn->buf, buf, x_read)) {
779
CONN_LOG_EX(32, Read, eLOG_Critical, "Cannot save peek data", 0);
780
conn->state = eCONN_Bad;
783
conn->r_pos += (TNCBI_BigCount) x_read;
698
786
if (status != eIO_Success) {
700
788
CONN_TRACE(Read, "Read error");
701
status = eIO_Success;
789
/*status = eIO_Success;*/
702
790
} else if (size && status != eIO_Closed) {
703
791
ELOG_Level level;
704
792
if (status != eIO_Timeout || conn->r_timeout == kDefaultTimeout)
731
819
status = s_CONN_Read(conn, (char*) buf + *n_read,
732
820
size - *n_read, &x_read, 0/*no peek*/);
733
821
*n_read += x_read;
734
if (*n_read == size || status != eIO_Success)
822
if (*n_read == size) {
823
conn->r_status = status;
824
return conn->flags & fCONN_Supplement ? status : eIO_Success;
827
if (status != eIO_Success)
736
830
/* keep flushing unwritten output data (if any) */
737
if (conn->meta.flush) {
738
conn->meta.flush(conn->meta.c_flush,
739
conn->r_timeout == kDefaultTimeout
740
? conn->meta.default_timeout
831
if (!(conn->flags & (fCONN_Untie | fCONN_Flush))) {
832
if (conn->meta.flush &&
833
conn->meta.flush(conn->meta.c_flush,
834
conn->r_timeout == kDefaultTimeout
835
? conn->meta.default_timeout
836
: conn->r_timeout) == eIO_Success) {
837
conn->flags |= fCONN_Flush;
842
conn->r_status = status;
756
854
EIO_Status status;
759
return eIO_InvalidArg;
762
return eIO_InvalidArg;
764
856
CONN_NOT_NULL(24, Read);
766
if (conn->state == eCONN_Unusable)
859
return eIO_InvalidArg;
767
862
return eIO_InvalidArg;
769
864
/* perform open, if not opened yet */
770
865
if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success)
772
assert(conn->state == eCONN_Open && conn->meta.list);
867
assert((conn->state & eCONN_Open) && conn->meta.list);
774
/* flush the unwritten output data (if any) */
775
if (conn->meta.flush) {
776
conn->meta.flush(conn->meta.c_flush,
777
conn->r_timeout == kDefaultTimeout
778
? conn->meta.default_timeout
869
/* flush unwritten output data (if any) */
870
if (!(conn->flags & (fCONN_Untie | fCONN_Flush))) {
871
if (conn->meta.flush &&
872
conn->meta.flush(conn->meta.c_flush,
873
conn->r_timeout == kDefaultTimeout
874
? conn->meta.default_timeout
875
: conn->r_timeout) == eIO_Success) {
876
conn->flags |= fCONN_Flush;
782
880
/* now do read */
883
status = s_CONN_Read(conn, buf, size, n_read, 1/*i.e.peek*/);
784
885
case eIO_ReadPlain:
785
return s_CONN_Read(conn, buf, size, n_read, 0/*no peek*/);
787
return s_CONN_Read(conn, buf, size, n_read, 1/*peek*/);
886
status = s_CONN_Read(conn, buf, size, n_read, 0/*i.e.read*/);
788
888
case eIO_ReadPersist:
789
889
return s_CONN_ReadPersist(conn, buf, size, n_read);
890
case eIO_ReadSupplement:
891
conn->r_status = s_CONN_Read(conn, buf, size, n_read, 0/*i.e.read*/);
892
return conn->r_status;
894
return eIO_NotSupported;
897
conn->r_status = status;
898
if (conn->flags & fCONN_Supplement)
900
return *n_read ? eIO_Success : status;
841
937
size_t x_size = BUF_Size(conn->buf);
842
938
char* x_buf = size - len < sizeof(w) ? w : line + len;
843
939
if (x_size == 0 || x_size > sizeof(w))
942
/* flush any pending output then read */
943
if (!(conn->flags & (fCONN_Untie | fCONN_Flush))) {
944
if (conn->meta.flush &&
945
conn->meta.flush(conn->meta.c_flush,
946
conn->r_timeout == kDefaultTimeout
947
? conn->meta.default_timeout
948
: conn->r_timeout) == eIO_Success) {
949
conn->flags |= fCONN_Flush;
845
952
status = s_CONN_Read(conn, x_buf, size ? x_size : 0, &x_read, 0);
953
conn->r_status = status;
846
955
for (i = 0; i < x_read && len < size; i++) {
847
956
char c = x_buf[i];
1033
extern EIO_Status CONN_Cancel(CONN conn)
1037
CONN_NOT_NULL(33, Cancel);
1039
if (conn->state == eCONN_Unusable)
1040
return eIO_InvalidArg;
1042
if (conn->state == eCONN_Cancel)
1043
return eIO_Interrupt;
1045
if (conn->state != eCONN_Open)
1048
if ((status = x_Callback(conn, eCONN_OnCancel)) == eIO_Success)
1049
conn->state = eCONN_Cancel;
912
1054
extern EIO_Status CONN_SetCallback
914
1056
ECONN_Callback type,
915
const SCONN_Callback* new_cb,
916
SCONN_Callback* old_cb)
1057
const SCONN_Callback* newcb,
1058
SCONN_Callback* oldcb)
919
if (i >= CONN_N_CALLBACKS)
920
return eIO_InvalidArg;
922
1062
CONN_NOT_NULL(28, SetCallback);
925
*old_cb = conn->cbs[i];
927
conn->cbs[i] = *new_cb;
1064
if ((i = (int) type) >= CONN_N_CALLBACKS) {
1065
static const STimeout* timeout = 0/*dummy*/;
1067
sprintf(errbuf, "Unknown callback type #%u", (unsigned int) i);
1068
CONN_LOG_EX(29, SetCallback, eLOG_Error, errbuf, eIO_InvalidArg);
1069
return eIO_InvalidArg;
1072
/* NB: oldcb and newcb may point to the same address */
1073
if (newcb || oldcb) {
1074
SCONN_Callback cb = conn->cb[i];
1076
conn->cb[i] = *newcb;
928
1080
return eIO_Success;