~ubuntu-branches/ubuntu/raring/ncbi-tools6/raring

« back to all changes in this revision

Viewing changes to connect/ncbi_connection.c

  • Committer: Package Import Robot
  • Author(s): Aaron M. Ucko
  • Date: 2011-09-05 18:55:02 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110905185502-iuvmoe65ytljhckn
Tags: 6.1.20110713-1
* New upstream release.
* debian/*.symbols: update accordingly.
* make/makeshlb.unx: link libcn3dOGL.so against -lm for sqrt.
* doc/man/*.1: update for new release.
* debian/rules:
  - (VIB): add asnmacro, as upstream takes care to publish binaries thereof.
  - Retire obsolete multiarch-unaware checks for libpthread.
  - Fully modernize Debhelper usage; in particular, transition to overrides.
* debian/compat: advance to 9 per rules modernization.
* debian/ncbi-tools-bin.install: add asnmacro.
* make/makenet.unx: link asnmacro only against libraries it directly needs.
* doc/man/asnmacro.1: give asnmacro a man page.
* doc/man/Psequin.1: list it in SEE ALSO.
* network/id1arch/idfetch.c: revert redundant change (from #295110).
* Convert to multiarch.
  - debian/rules: Install libraries (and ncbithr.o) to multiarch directories.
  - debian/lib*.install: match multiarch library paths.
  - debian/control:
    + Build-Depends: debhelper (>= 8.1.3~), implying a recent dpkg-dev.
    + Set Multi-Arch: as appropriate across the board, and specify
      Pre-Depends: ${misc:Pre-Depends} for runtime libraries.
* debian/*.lintian-overrides: drop leading slashes for Lintian 2.5.x.
* debian/control: Standards-Version: 3.9.2 (already compliant).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: ncbi_connection.c,v 6.65 2010/07/13 16:04:35 kazimird Exp $
 
1
/* $Id: ncbi_connection.c,v 6.77 2011/06/02 14:19:31 kazimird Exp $
2
2
 * ===========================================================================
3
3
 *
4
4
 *                            PUBLIC DOMAIN NOTICE
37
37
#include <stdlib.h>
38
38
#include <string.h>
39
39
 
40
 
#define NCBI_USE_ERRCODE_X   Connect_Connection
 
40
#define NCBI_USE_ERRCODE_X   Connect_Conn
41
41
 
42
42
#define CONNECTION_MAGIC     0xEFCDAB09
43
43
 
51
51
#define CONN_LOG_EX(subcode, func_name, level, message, status)            \
52
52
  do {                                                                     \
53
53
      const char* ststr = status ? IO_StatusStr((EIO_Status) status) : ""; \
54
 
      const char* ctype = (conn->meta.get_type                             \
 
54
      const char* ctype = (conn  &&  conn->meta.get_type                   \
55
55
                           ? conn->meta.get_type(conn->meta.c_get_type)    \
56
56
                           : 0);                                           \
57
 
      char* descr = (conn->meta.descr                                      \
 
57
      char* descr = (conn  &&  conn->meta.descr                            \
58
58
                     ? conn->meta.descr(conn->meta.c_descr)                \
59
59
                     : 0);                                                 \
60
60
      char stbuf[80];                                                      \
67
67
      }                                                                    \
68
68
      CORE_LOGF_X(subcode, level,                                          \
69
69
                  ("[CONN_" #func_name "(%s%s%s)]  %s%s%s",                \
70
 
                   ctype  &&  *ctype ? ctype : "UNKNOWN",                  \
 
70
                   ctype  &&  *ctype ? ctype : "UNDEF",                    \
71
71
                   descr  &&  *descr ? "; "  : "", descr ? descr : "",     \
72
72
                   message,                                                \
73
73
                   ststr  &&  *ststr ? ": "  : "",                         \
84
84
#define CONN_NOT_NULL_EX(subcode, func_name, retval)                    \
85
85
  do {                                                                  \
86
86
      if (!conn) {                                                      \
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);                \
90
90
          assert(conn);                                                 \
91
91
          return retval;                                                \
92
92
      }                                                                 \
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);                \
97
97
      }                                                                 \
98
98
  } while (0)
99
99
 
106
106
#endif /*_DEBUG*/
107
107
 
108
108
 
 
109
/* Private flags, must not cross with ECONN_Flags defined in the header
 
110
 */
 
111
typedef enum {
 
112
    fCONN_Flush = 1024                 /* auto-flush was successful          */
 
113
} ECONN_InternalFlags;
 
114
 
 
115
 
109
116
/* Connection state
110
117
 */
111
118
typedef enum ECONN_StateTag {
112
119
    eCONN_Unusable = -1,               /* iff !conn->meta.list               */
113
 
    eCONN_Closed   =  0,
114
 
    eCONN_Open     =  1,
115
 
    eCONN_Bad      =  2
 
120
    eCONN_Closed   =  0,               /* "Open" can be attempted            */
 
121
    eCONN_Open     =  1,               /* operational state (I/O allowed)    */
 
122
    eCONN_Bad      =  2,               /* non-operational (I/O not allowed)  */
 
123
    eCONN_Cancel   =  3                /* NB: |= eCONN_Open (user-canceled)  */
116
124
} ECONN_State;
117
125
 
118
126
 
121
129
typedef struct SConnectionTag {
122
130
    SMetaConnector         meta;       /* VTable of operations and list      */
123
131
 
124
 
    BUF                    buf;        /* storage for the Peek'd data        */
125
132
    ECONN_State            state;      /* connection state                   */
 
133
    TCONN_Flags            flags;      /* connection flags                   */
 
134
    EIO_Status             r_status;
 
135
    EIO_Status             w_status;
 
136
 
 
137
    BUF                    buf;        /* storage for peek data              */
126
138
 
127
139
    /* "[c|r|w|l]_timeout" is either 0 (kInfiniteTimeout), kDefaultTimeout
128
140
       (to use connector-specific one), or points to "[cc|rr|ww|ll]_timeout" */
135
147
    STimeout               ww_timeout; /* storage for "w_timeout"            */
136
148
    STimeout               cc_timeout; /* storage for "c_timeout"            */
137
149
 
138
 
    SCONN_Callback         cbs[CONN_N_CALLBACKS];
 
150
    TNCBI_BigCount         r_pos;      /* read and ...                       */
 
151
    TNCBI_BigCount         w_pos;      /*          ... write positions       */
 
152
 
 
153
    SCONN_Callback         cb[CONN_N_CALLBACKS];
139
154
 
140
155
    unsigned int           magic;      /* magic number for integrity checks  */
141
156
} SConnection;
142
157
 
143
158
 
144
 
static EIO_Status x_ReInit
145
 
(CONN      conn,
146
 
 CONNECTOR connector)
147
 
{
148
 
    CONNECTOR       x_conn;
149
 
    EIO_Status      status;
150
 
    const STimeout* timeout = 0/*dummy*/;
 
159
static EIO_Status x_Callback(CONN conn, ECONN_Callback type)
 
160
{
 
161
    FCONN_Callback func;
 
162
    void*          data;
 
163
 
 
164
    assert(conn  &&  (int) type >= 0  &&  (int) type < CONN_N_CALLBACKS);
 
165
    if (conn->state == eCONN_Unusable)
 
166
        return eIO_Closed;
 
167
    if (!(func = conn->cb[type].func))
 
168
        return eIO_Success;
 
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);
 
173
}
 
174
 
 
175
 
 
176
static EIO_Status x_ReInit(CONN conn, CONNECTOR connector)
 
177
{
 
178
    static const STimeout* timeout = 0/*dummy*/;
 
179
    EIO_Status status;
 
180
    CONNECTOR  x_conn;
151
181
 
152
182
    assert(conn->meta.list  ||  conn->state == eCONN_Unusable);
153
183
 
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
162
 
                                 : conn->c_timeout);
163
 
            }
164
 
        }
165
 
    }
 
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
 
189
                           : conn->c_timeout)
 
190
        : eIO_Success;
166
191
 
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)
171
196
                break;
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;
174
200
            return status;
175
201
        }
176
202
    }
177
203
 
178
 
    if (!x_conn) {
179
 
        FConnCallback func;
180
 
        void*         data;
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;
186
 
        } else {
187
 
            func = 0;
188
 
            data = 0;
189
 
        }
190
 
        /* allow close CB only once */
191
 
        memset(&conn->cbs[eCONN_OnClose], 0, sizeof(conn->cbs[eCONN_OnClose]));
192
 
        /* call it! */
193
 
        if (func)
194
 
            func(conn, eCONN_OnClose, data);
195
 
    }
196
 
 
197
204
    if (conn->meta.list) {
198
 
        /* erase unread data */
 
205
        /* Erase unread data */
199
206
        BUF_Erase(conn->buf);
200
207
 
201
 
        if (conn->state == eCONN_Open) {
202
 
            /* call current connector's "CLOSE" method */
 
208
        if (!x_conn) {
 
209
            /* NB: Re-init with same connector does not cause the callback */
 
210
            status = x_Callback(conn, eCONN_OnClose);
 
211
        }
 
212
 
 
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,
 
216
                EIO_Status closed;
 
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");
211
 
                    if (connector) {
212
 
                        conn->state = eCONN_Bad;
213
 
                        return status;
214
 
                    }
215
 
                }
216
 
            }
217
 
            conn->state = eCONN_Closed;
 
221
                if (closed != eIO_Success)
 
222
                    status  = closed;
 
223
            }
 
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");
 
228
            }
218
229
        }
219
230
 
220
231
        if (!x_conn) {
223
234
            assert(!conn->meta.list);
224
235
            memset(&conn->meta, 0, sizeof(conn->meta));
225
236
            conn->state = eCONN_Unusable;
226
 
        }
227
 
    }
 
237
        } else if (status != eIO_Success) {
 
238
            conn->state = eCONN_Bad;
 
239
            return status;
 
240
        } else
 
241
            conn->state = eCONN_Closed;
 
242
    } else if (!connector)
 
243
        status = eIO_Closed;
228
244
 
229
245
    if (!x_conn  &&  connector) {
230
246
        assert(conn->state == eCONN_Unusable);
236
252
    }
237
253
 
238
254
    assert(conn->state != eCONN_Open  &&  conn->state != eCONN_Bad);
239
 
    return eIO_Success;
 
255
    return status;
240
256
}
241
257
 
242
258
 
243
 
static EIO_Status s_Open
244
 
(CONN conn)
 
259
static EIO_Status s_Open(CONN conn)
245
260
{
246
261
    const STimeout* timeout;
247
262
    EIO_Status      status;
248
263
 
249
 
    if (conn->state == eCONN_Bad)
 
264
    switch (conn->state) {
 
265
    case eCONN_Unusable:
 
266
        return eIO_InvalidArg;
 
267
    case eCONN_Bad:
250
268
        return eIO_Closed;
251
 
 
 
269
    case eCONN_Cancel:
 
270
        return eIO_Interrupt;
 
271
    default:
 
272
        break;
 
273
    }
252
274
    assert(conn->state == eCONN_Closed  &&  conn->meta.list);
253
275
 
254
276
    /* call current connector's "OPEN" method */
262
284
        timeout = 0/*dummy*/;
263
285
    }
264
286
 
265
 
    if (status != eIO_Success) {
 
287
    if (status == eIO_Success) {
 
288
        conn->r_pos    = 0;
 
289
        conn->w_pos    = 0;
 
290
        conn->flags   &= ~fCONN_Flush;
 
291
        conn->r_status = eIO_Success;
 
292
        conn->w_status = eIO_Success;
 
293
        conn->state = eCONN_Open;
 
294
    } else {
266
295
        CONN_LOG(5, Open, eLOG_Error, "Failed to open connection");
267
296
        conn->state = eCONN_Bad;
268
 
    } else
269
 
        conn->state = eCONN_Open;
 
297
    }
270
298
    return status;
271
299
}
272
300
 
275
303
 *  EXTERNAL
276
304
 ***********************************************************************/
277
305
 
 
306
extern EIO_Status CONN_CreateEx
 
307
(CONNECTOR   connector,
 
308
 TCONN_Flags flags,
 
309
 CONN*       connection)
 
310
{
 
311
    EIO_Status status;
 
312
    CONN       conn;
 
313
 
 
314
    if (connector) {
 
315
        conn = (SConnection*) calloc(1, sizeof(SConnection));
 
316
 
 
317
        if (conn) {
 
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) {
 
326
                free(conn);
 
327
                conn = 0;
 
328
            }
 
329
        } else
 
330
            status = eIO_Unknown;
 
331
    } else {
 
332
        static const STimeout* timeout = 0/*dummy*/;
 
333
        conn = 0;
 
334
        status = eIO_InvalidArg;
 
335
        CONN_LOG(2, Create, eLOG_Error, "NULL connector");
 
336
    }
 
337
 
 
338
    *connection = conn;
 
339
    return status;
 
340
}
 
341
 
 
342
 
278
343
extern EIO_Status CONN_Create
279
344
(CONNECTOR connector,
280
 
 CONN*     connection)
 
345
 CONN*     conn)
281
346
{
282
 
    EIO_Status status;
283
 
    CONN       conn;
284
 
 
285
 
    if (!connector)
286
 
        return eIO_InvalidArg;
287
 
 
288
 
    conn = (SConnection*) calloc(1, sizeof(SConnection));
289
 
 
290
 
    if (conn) {
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) {
298
 
            free(conn);
299
 
            conn = 0;
300
 
        }
301
 
    } else
302
 
        status = eIO_Unknown;
303
 
 
304
 
    *connection = conn;
305
 
    return status;
 
347
    return CONN_CreateEx(connector, 0, conn);
306
348
}
307
349
 
308
350
 
310
352
(CONN      conn,
311
353
 CONNECTOR connector)
312
354
{
313
 
    const STimeout* timeout = 0/*dummy*/;
314
 
    EIO_Status status;
315
 
 
316
355
    CONN_NOT_NULL(1, ReInit);
317
356
 
318
 
    /* check arg */
319
 
    if (!connector  &&  !conn->meta.list) {
320
 
        assert(conn->state == eCONN_Unusable);
321
 
        status = eIO_InvalidArg;
322
 
        CONN_LOG(2, ReInit, eLOG_Error,
323
 
                 "Cannot re-init empty connection with NULL");
324
 
        return status;
325
 
    }
326
 
 
327
357
    return x_ReInit(conn, connector);
328
358
}
329
359
 
392
422
            conn->c_timeout  = timeout;
393
423
        break;
394
424
    default:
395
 
        sprintf(errbuf, "Unknown event #%d to set timeout for", (int) event);
 
425
        sprintf(errbuf, "Unknown event #%u", (unsigned int) event);
396
426
        CONN_LOG_EX(9, SetTimeout, eLOG_Error, errbuf, eIO_InvalidArg);
397
427
        return eIO_InvalidArg;
398
428
    }
401
431
}
402
432
 
403
433
 
 
434
extern TNCBI_BigCount CONN_GetPosition(CONN conn, EIO_Event event)
 
435
{
 
436
    static const STimeout* timeout = 0/*dummy*/;
 
437
    char errbuf[80];
 
438
 
 
439
    CONN_NOT_NULL_EX(30, GetPosition, 0);
 
440
 
 
441
    switch (event) {
 
442
    case eIO_Open:
 
443
        conn->r_pos = 0;
 
444
        conn->w_pos = 0;
 
445
        break;
 
446
    case eIO_Read:
 
447
        return conn->r_pos;
 
448
    case eIO_Write:
 
449
        return conn->w_pos;
 
450
    default:
 
451
        sprintf(errbuf, "Unknown direction #%u", (unsigned int) event);
 
452
        CONN_LOG_EX(31, GetPosition, eLOG_Error, errbuf, 0);
 
453
        assert(0);
 
454
        break;
 
455
    }
 
456
 
 
457
    return 0;
 
458
}
 
459
 
 
460
 
404
461
extern const STimeout* CONN_GetTimeout
405
462
(CONN      conn,
406
463
 EIO_Event event)
429
486
        timeout = conn->c_timeout;
430
487
        break;
431
488
    default:
432
 
        timeout = 0/*dummy*/;
433
 
        sprintf(errbuf, "Unknown event #%d to get timeout for", (int) event);
 
489
        timeout = 0;
 
490
        sprintf(errbuf, "Unknown event #%u", (unsigned int) event);
434
491
        CONN_LOG_EX(12, GetTimeout, eLOG_Error, errbuf, 0);
435
492
        assert(0);
436
493
        break;
437
494
    }
 
495
 
438
496
    return timeout;
439
497
}
440
498
 
448
506
 
449
507
    CONN_NOT_NULL(13, Wait);
450
508
 
451
 
    if (conn->state == eCONN_Unusable                ||
452
 
        (event != eIO_Read  &&  event != eIO_Write)  ||
453
 
        timeout == kDefaultTimeout) {
 
509
    if ((event != eIO_Read  &&  event != eIO_Write)
 
510
        ||  timeout == kDefaultTimeout) {
454
511
        return eIO_InvalidArg;
455
512
    }
456
513
 
457
514
    /* perform open, if not opened yet */
458
515
    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
459
516
        return status;
460
 
    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
517
    assert((conn->state & eCONN_Open)  &&  conn->meta.list);
461
518
 
462
519
    /* check if there is a PEEK'ed data in the input */
463
520
    if (event == eIO_Read  &&  BUF_Size(conn->buf))
498
555
 
499
556
 
500
557
static EIO_Status s_CONN_Write
501
 
(CONN        conn,
502
 
 const void* buf,
503
 
 size_t      size,
504
 
 size_t*     n_written)
 
558
(CONN         conn,
 
559
 const void*  buf,
 
560
 const size_t size,
 
561
 size_t*      n_written)
505
562
{
506
563
    const STimeout* timeout;
507
564
    EIO_Status status;
508
565
 
509
566
    assert(*n_written == 0);
510
567
 
 
568
    if (conn->state == eCONN_Cancel)
 
569
        return eIO_Interrupt;
 
570
 
511
571
    /* check if the write method is specified at all */
512
572
    if (!conn->meta.write) {
513
573
        timeout = 0/*dummy*/;
516
576
        return status;
517
577
    }
518
578
 
 
579
    if ((status = x_Callback(conn, eCONN_OnWrite)) != eIO_Success)
 
580
        return status;
 
581
 
519
582
    /* call current connector's "WRITE" method */
520
583
    timeout = (conn->w_timeout == kDefaultTimeout
521
584
               ? conn->meta.default_timeout
523
586
    status = conn->meta.write(conn->meta.c_write, buf, size,
524
587
                              n_written, timeout);
525
588
 
 
589
    if (*n_written) {
 
590
        conn->flags &= ~fCONN_Flush;
 
591
        conn->w_pos += (TNCBI_BigCount)(*n_written);
 
592
    }
 
593
 
526
594
    if (status != eIO_Success) {
527
595
        if (*n_written) {
528
596
            CONN_TRACE(Write, "Write error");
529
 
            status = eIO_Success;
 
597
            /*status = eIO_Success;*/
530
598
        } else if (size) {
531
599
            ELOG_Level level;
532
600
            if (status != eIO_Timeout  ||  conn->w_timeout == kDefaultTimeout)
543
611
 
544
612
 
545
613
static EIO_Status s_CONN_WritePersist
546
 
(CONN        conn,
547
 
 const void* buf,
548
 
 size_t      size,
549
 
 size_t*     n_written)
 
614
(CONN         conn,
 
615
 const void*  buf,
 
616
 const size_t size,
 
617
 size_t*      n_written)
550
618
{
551
619
    EIO_Status status;
552
620
 
557
625
        status = s_CONN_Write(conn, (char*) buf + *n_written,
558
626
                              size - *n_written, &x_written);
559
627
        *n_written += x_written;
560
 
    } while (*n_written != size  &&  status == eIO_Success);
 
628
        if (*n_written == size) {
 
629
            conn->w_status = status;
 
630
            return conn->flags & fCONN_Supplement ? status : eIO_Success;
 
631
        }
 
632
    } while (status == eIO_Success);
561
633
 
 
634
    conn->w_status = status;
562
635
    return status;
563
636
}
564
637
 
572
645
{
573
646
    EIO_Status status;
574
647
 
 
648
    CONN_NOT_NULL(18, Write);
 
649
 
575
650
    if (!n_written)
576
651
        return eIO_InvalidArg;
577
652
    *n_written = 0;
578
653
    if (size  &&  !buf)
579
654
        return eIO_InvalidArg;
580
655
 
581
 
    CONN_NOT_NULL(18, Write);
582
 
 
583
 
    if (conn->state == eCONN_Unusable)
584
 
        return eIO_InvalidArg;
585
 
 
586
656
    /* open connection, if not yet opened */
587
657
    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
588
658
        return status;
589
 
    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
659
    assert((conn->state & eCONN_Open)  &&  conn->meta.list);
590
660
 
591
661
    switch (how) {
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);
 
664
        break;
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;
596
670
    default:
597
 
        break;
 
671
        return eIO_NotSupported;
598
672
    }
599
 
    return eIO_Unknown;
 
673
 
 
674
    conn->w_status = status;
 
675
    if (conn->flags & fCONN_Supplement)
 
676
        return status;
 
677
    return *n_written ? eIO_Success : status;
600
678
}
601
679
 
602
680
 
625
703
 
626
704
    CONN_NOT_NULL(20, Flush);
627
705
 
628
 
    if (conn->state == eCONN_Unusable)
629
 
        return eIO_InvalidArg;
630
 
 
631
706
    /* perform open, if not opened yet */
632
707
    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
633
708
        return status;
634
 
    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
709
    assert((conn->state & eCONN_Open)  &&  conn->meta.list);
635
710
 
636
711
    /* call current connector's "FLUSH" method */
637
 
    if (!conn->meta.flush)
638
 
        return eIO_Success;
639
 
    timeout = (conn->w_timeout == kDefaultTimeout
640
 
               ? conn->meta.default_timeout
641
 
               : conn->w_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
 
715
                   : conn->w_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");
 
719
        else
 
720
            conn->flags |= fCONN_Flush;
 
721
        conn->w_status = status;
 
722
    } else
 
723
        status = eIO_Success;
643
724
 
644
 
    if (status != eIO_Success)
645
 
        CONN_LOG(21, Flush, eLOG_Warning, "Failed to flush");
646
725
    return status;
647
726
}
648
727
 
650
729
/* Read or peek data from the input queue, see CONN_Read()
651
730
 */
652
731
static EIO_Status s_CONN_Read
653
 
(CONN        conn,
654
 
 void*       buf,
655
 
 size_t      size,
656
 
 size_t*     n_read,
657
 
 int/*bool*/ peek)
 
732
(CONN         conn,
 
733
 void*        buf,
 
734
 const size_t size,
 
735
 size_t*      n_read,
 
736
 int/*bool*/  peek)
658
737
{
659
738
    const STimeout* timeout;
660
739
    EIO_Status status;
661
740
 
662
741
    assert(*n_read == 0);
663
742
 
 
743
    if (conn->state == eCONN_Cancel)
 
744
        return eIO_Interrupt;
 
745
 
664
746
    /* check if the read method is specified at all */
665
747
    if (!conn->meta.read) {
666
748
        timeout = 0/*dummy*/;
667
749
        status = eIO_NotSupported;
668
 
        CONN_LOG(22, Read, eLOG_Error, "Cannot read data");
 
750
        CONN_LOG(22, Read, eLOG_Critical, "Cannot read data");
669
751
        return status;
670
752
    }
671
753
 
679
761
        buf = (char*) buf + *n_read;
680
762
    }
681
763
 
682
 
    /* read data from the connection */
 
764
    if ((status = x_Callback(conn, eCONN_OnRead)) != eIO_Success)
 
765
        return status;
 
766
 
 
767
    /* call current connector's "READ" method */
683
768
    {{
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;
692
776
 
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;
 
781
            status = eIO_Closed;
 
782
        } else
 
783
            conn->r_pos += (TNCBI_BigCount) x_read;
696
784
    }}
697
785
 
698
786
    if (status != eIO_Success) {
699
787
        if (*n_read) {
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)
717
805
/* Persistently read data from the input queue, see CONN_Read()
718
806
 */
719
807
static EIO_Status s_CONN_ReadPersist
720
 
(CONN    conn,
721
 
 void*   buf,
722
 
 size_t  size,
723
 
 size_t* n_read)
 
808
(CONN         conn,
 
809
 void*        buf,
 
810
 const size_t size,
 
811
 size_t*      n_read)
724
812
{
725
813
    EIO_Status status;
726
814
 
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;
 
825
        }
 
826
 
 
827
        if (status != eIO_Success)
735
828
            break;
 
829
 
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
741
 
                             : conn->r_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;
 
838
            }
742
839
        }
743
840
    }
744
841
 
 
842
    conn->r_status = status;
745
843
    return status;
746
844
}
747
845
 
755
853
{
756
854
    EIO_Status status;
757
855
 
758
 
    if (!n_read)
759
 
        return eIO_InvalidArg;
760
 
    *n_read = 0;
761
 
    if (size  &&  !buf)
762
 
        return eIO_InvalidArg;
763
 
 
764
856
    CONN_NOT_NULL(24, Read);
765
857
 
766
 
    if (conn->state == eCONN_Unusable)
 
858
    if (!n_read)
 
859
        return eIO_InvalidArg;
 
860
    *n_read = 0;
 
861
    if (size  &&  !buf)
767
862
        return eIO_InvalidArg;
768
863
 
769
864
    /* perform open, if not opened yet */
770
865
    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
771
866
        return status;
772
 
    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
867
    assert((conn->state & eCONN_Open)  &&  conn->meta.list);
773
868
 
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
779
 
                         : conn->r_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;
 
877
        }
780
878
    }
781
879
 
782
880
    /* now do read */
783
881
    switch (how) {
 
882
    case eIO_ReadPeek:
 
883
        status = s_CONN_Read(conn, buf, size, n_read, 1/*i.e.peek*/);
 
884
        break;
784
885
    case eIO_ReadPlain:
785
 
        return s_CONN_Read(conn, buf, size, n_read, 0/*no peek*/);
786
 
    case eIO_ReadPeek:
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*/);
 
887
        break;
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;
790
893
    default:
791
 
        break;
 
894
        return eIO_NotSupported;
792
895
    }
793
 
    return eIO_Unknown;
 
896
 
 
897
    conn->r_status = status;
 
898
    if (conn->flags & fCONN_Supplement)
 
899
        return status;
 
900
    return *n_read ? eIO_Success : status;
794
901
}
795
902
 
796
903
 
805
912
    int/*bool*/ done;
806
913
    size_t      len;
807
914
 
 
915
    CONN_NOT_NULL(25, ReadLine);
 
916
 
808
917
    if (!n_read)
809
918
        return eIO_InvalidArg;
810
919
    *n_read = 0;
814
923
        *line = '\0';
815
924
    }
816
925
 
817
 
    CONN_NOT_NULL(25, ReadLine);
818
 
 
819
 
    if (conn->state == eCONN_Unusable)
820
 
        return eIO_InvalidArg;
821
 
 
822
926
    /* perform open, if not opened yet */
823
927
    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
824
928
        return status;
825
 
    assert(conn->state == eCONN_Open  &&  conn->meta.list);
826
 
 
827
 
    /* flush the unwritten output data (if any) */
828
 
    if (conn->meta.flush) {
829
 
        conn->meta.flush(conn->meta.c_flush,
830
 
                         conn->r_timeout == kDefaultTimeout
831
 
                         ? conn->meta.default_timeout
832
 
                         : conn->r_timeout);
833
 
    }
 
929
    assert((conn->state & eCONN_Open)  &&  conn->meta.list);
834
930
 
835
931
    len = 0;
836
932
    done = 0/*false*/;
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))
844
 
            x_size = sizeof(w);
 
940
            x_size  = sizeof(w);
 
941
 
 
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;
 
950
            }
 
951
        }
845
952
        status = s_CONN_Read(conn, x_buf, size ? x_size : 0, &x_read, 0);
 
953
        conn->r_status = status;
 
954
 
846
955
        for (i = 0; i < x_read  &&  len < size; i++) {
847
956
            char c = x_buf[i];
848
957
            if (c == '\n') {
857
966
        if (i < x_read) {
858
967
            assert(done  ||  len >= size);
859
968
            if (!BUF_PushBack(&conn->buf, x_buf + i, x_read - i)) {
860
 
                const STimeout* timeout = 0/*dummy*/;
861
 
                CONN_LOG_EX(15, ReadLine, eLOG_Error,
 
969
                static const STimeout* timeout = 0/*dummy*/;
 
970
                CONN_LOG_EX(15, ReadLine, eLOG_Critical,
862
971
                            "Cannot pushback extra data", 0);
863
 
                status = eIO_Unknown;
 
972
                conn->state = eCONN_Bad;
 
973
                status = eIO_Closed;
864
974
            } else
865
975
                status = eIO_Success;
866
976
            break;
878
988
{
879
989
    CONN_NOT_NULL(26, Status);
880
990
 
881
 
    if (conn->state == eCONN_Unusable)
882
 
        return eIO_InvalidArg;
883
 
 
884
991
    if (dir != eIO_Read  &&  dir != eIO_Write)
885
992
        return eIO_InvalidArg;
886
993
 
 
994
    if (conn->state == eCONN_Unusable)
 
995
        return eIO_InvalidArg;
 
996
 
 
997
    if (conn->state == eCONN_Cancel)
 
998
        return eIO_Interrupt;
 
999
 
887
1000
    if (conn->state != eCONN_Open)
888
1001
        return eIO_Closed;
889
1002
 
 
1003
    if (dir == eIO_Read) {
 
1004
        if (conn->r_status != eIO_Success)
 
1005
            return conn->r_status;
 
1006
    } else {
 
1007
        if (conn->w_status != eIO_Success)
 
1008
            return conn->w_status;
 
1009
    }
 
1010
 
890
1011
    if (!conn->meta.status)
891
1012
        return eIO_NotSupported;
892
1013
 
909
1030
}
910
1031
 
911
1032
 
 
1033
extern EIO_Status CONN_Cancel(CONN conn)
 
1034
{
 
1035
    EIO_Status status;
 
1036
 
 
1037
    CONN_NOT_NULL(33, Cancel);
 
1038
    
 
1039
    if (conn->state == eCONN_Unusable)
 
1040
        return eIO_InvalidArg;
 
1041
 
 
1042
    if (conn->state == eCONN_Cancel)
 
1043
        return eIO_Interrupt;
 
1044
 
 
1045
    if (conn->state != eCONN_Open)
 
1046
        return eIO_Closed;
 
1047
 
 
1048
    if ((status = x_Callback(conn, eCONN_OnCancel)) == eIO_Success)
 
1049
        conn->state = eCONN_Cancel;
 
1050
    return status;
 
1051
}
 
1052
 
 
1053
 
912
1054
extern EIO_Status CONN_SetCallback
913
1055
(CONN                  conn,
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)
917
1059
{
918
 
    int i = (int) type;
919
 
    if (i >= CONN_N_CALLBACKS)
920
 
        return eIO_InvalidArg;
 
1060
    int i;
921
1061
 
922
1062
    CONN_NOT_NULL(28, SetCallback);
923
1063
 
924
 
    if (old_cb)
925
 
        *old_cb = conn->cbs[i];
926
 
    if (new_cb)
927
 
        conn->cbs[i] = *new_cb;
 
1064
    if ((i = (int) type) >= CONN_N_CALLBACKS) {
 
1065
        static const STimeout* timeout = 0/*dummy*/;
 
1066
        char errbuf[80];
 
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;
 
1070
    }
 
1071
 
 
1072
    /* NB: oldcb and newcb may point to the same address */
 
1073
    if (newcb  ||  oldcb) {
 
1074
        SCONN_Callback cb = conn->cb[i];
 
1075
        if (newcb)
 
1076
            conn->cb[i] = *newcb;
 
1077
        if (oldcb)
 
1078
            *oldcb = cb;
 
1079
    }
928
1080
    return eIO_Success;
929
1081
}