source: git/MP/MP/MP_Link.c @ 1d0eb7

fieker-DuValspielwiese
Last change on this file since 1d0eb7 was a3600c, checked in by Hans Schönemann <hannes@…>, 25 years ago
* hannes: glibc-fixes: rename errno of an MP link to MP_errno git-svn-id: file:///usr/local/Singular/svn/trunk@2978 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 47.6 KB
Line 
1/*******************************************************************
2 *                                                                   
3 *                    MP version 1.1.2:  Multi Protocol
4 *                    Kent State University, Kent, OH
5 *                 Authors:  S. Gray, N. Kajler, P. Wang
6 *          (C) 1993, 1994, 1995, 1996, 1997 All Rights Reserved
7 *
8 *                                 NOTICE
9 *
10 *  Permission to use, copy, modify, and distribute this software and
11 *  its documentation for non-commercial purposes and without fee is
12 *  hereby granted provided that the above copyright notice appear in all
13 *  copies and that both the copyright notice and this permission notice
14 *  appear in supporting documentation.
15 * 
16 *  Neither Kent State University nor the Authors make any representations
17 *  about the suitability of this software for any purpose.  The MP Library
18 *  is distributed in the hope that it will be useful, but is provided  "as
19 *  is" and without any warranty of any kind and without even the implied 
20 *  warranty of merchantability or fitness for a particular purpose.
21 *
22 *
23 *   IMPLEMENTATION FILE:  MP_Link.c
24 *
25 *      General routines associated with a link.
26 *      This code provides the buffering layer above tcp/ip for Multi.
27 *      The code is largely the RPC buffering code with a few .
28 *      modifications
29 *
30 *  Change Log:
31 *                Jan 30  Added m_restore(link) SG
32 *                        Added m_eot(link) SG
33 *                        changed RECSTREAM * to MP_Link_pt SG
34 *
35 *                May 25, 1995  baw
36 *                  Added:
37 *                    structures:
38 *                        buffer_handle
39 *                        buffer_pool
40 *                    routines:
41 *                        pool_init(buffer_size, max_free_buffer,
42 *                                  init_free_buffer)
43 *                        pool_destroy()
44 *                        create_buffer()
45 *                        destroy_buffer(buffer_handle)
46 *                        get_buffer()
47 *                        free_buffer(buffer_handle)
48 *                        get_o_buff(link)
49 *                        get_i_buff(link)
50 *                        free_o(link)
51 *                        free_i(link)
52 *                        --- 09-June-1995 ---
53 *                        reset_i_buff(link)
54 *                        fill_a_buff(link)
55 *                  Modified:
56 *                    structures:
57 *                        MP_Link_t
58 *                    routines:
59 *                        m_create_link(sock, num_o_buff, (*Readit)(),
60 *                                 (*writeit)(), snd_mode, rcv_mode)
61 *                        m_destroy(link)
62 *                        IMP_PutLong(link, *lp)
63 *                        IMP_PutBytes(link, addr, len)
64 *                        m_endofmessage(link)
65 *                        flush_out(buff)
66 *                        --- 09-June-1995 ---
67 *                        fill_input_buf(link)
68 *               
69 *                August 9, 1995 SG
70 *                    renamed free_i() to m_free_in_bufs()
71 *                            free_o() to m_free_out_bufs()
72 *                            pool_destroy() to m_free_pool()
73 *                            pool_init() to m_create_pool()
74 *                            m_destroy() to m_destroy_link()
75 *                            m_create() to m_create_link()
76 *
77 *              September 13, 1995 SG
78 *                  moved all the buffer code to MP_Buffer.c
79 *
80 *      11/18/95 obachman added ntohl(hdr) in fill_a_buf
81 *      11/25/95 sgray added defines to support negotiating
82 *               endian word order.
83 *       1/25/96 sgray formally added PVM device to MP_OpenLink().
84 *       1/29/96 sgray added MP_GetLinkOption() to return the current
85 *                     setting for an option.  Note that since we return
86 *                     MP_Failure for an illegal option, we must never
87 *                     allow a legal option to be the value MP_Failure (0).
88 *               sgray Improved the logging for MP_SetLinkOption().
89 *       3/3/96  sgray Changed the MP_OpenLink() routine to look for the
90 *                     requested device in the environment device list and
91 *                     call the device open routine from there.  We no
92 *                     longer call the device init routine, whose
93 *                     responsibilities have been shoved into the open fnc.
94 *       4/19/96 sgray Added support for alternative BigInt formats. This
95 *                     means that OpenLink() now loads GMP as the default
96 *                     BigInt package.
97 *       4/23/96 sgray Completed support for SAC big integers.
98 *       5/16/96 sgray Changed MP_PeekLink() to MP_PeekHeader().
99 *                     Made MP_EndMsgReset() a function instead of a macro.
100 *       8/21/96 sgray Restored recv_mode2string string array.
101 *                     Fixed error in MP_SetLinkOption(): send_mode2string
102 *                     was accessed instead of recv_mode2string
103 *       8/30/96 sgray Added test for NULL environment in MP_CloseLink()
104 *                     and MP_SkipMsg().
105 *       3/11/97 sgray Fixed bug in fill_input_buf() that made it appear
106 *                     that data had been read in when the read operation
107 *                     had returned failure.
108 *       3/11/97 sgray Added code to fill_a_buf() so that repeated
109 *                     attempts to read from an empty data stream (e.g.,
110 *                     an empty file) would fail.  Before this, a first
111 *                     attempt to read would fail but subsequent attempts
112 *                     would think there was data in the link because
113 *                     m_free_in_bufs(), invoked in fill_input_buf(), resets
114 *                     these two pointers to be the beginning (in_finger)
115 *                     and end (in_boundry) of an input buffer.  Other
116 *                     routines rely on this to know how much space there
117 *                     is to put data.
118 *       3/11/97 sgray Changed some "int"s to "unsigned long"s in fill_a_buf()
119 *                     and fill_input_buf().
120 *
121 ************************************************************************/
122
123/* @(#)xdr_rec.c        1.1 87/11/04 3.9 RPCSRC
124 * MP_Link.c, Implements TCP/IP based Multi links with a "message marking"
125 * layer above tcp (for rpc's use).
126 *
127 * Copyright (C) 1984, Sun Microsystems, Inc.
128 *
129 * These routines interface XDRSTREAMS to a tcp/ip connection.
130 * There is a message marking layer between the xdr link
131 * and the tcp transport level.  A message is composed on one or more
132 * message fragments.  A message fragment is a thirty-two bit header followed
133 * by n bytes of data, where n is contained in the header.  The header
134 * is represented as a htonl(unsigned long).  The order bit encodes
135 * whether or not the fragment is the last fragment of the message
136 * (1 => fragment is last, 0 => more fragments to follow.
137 * The other 31 bits encode the byte length of the fragment.
138 */
139
140#ifndef lint
141static char vcid[] = "@(#) $Id: MP_Link.c,v 1.5 1999-04-09 12:14:52 Singular Exp $";
142#endif /* lint */
143
144#include "MP.h"
145
146#define log_msg_len 128
147static char log_msg[log_msg_len];  /* for event logging */
148static char *msg = NULL;           /* for variable length logging messages */
149static char *send_mode2string[2] = {"MP_SEND_FRAG_MSG", "MP_SEND_WHOLE_MSG"};
150static char *recv_mode2string[3] = {"MP_RECV_FRAG_MSG_RECVER",
151                                    "MP_RECV_FRAG_MSG_SENDER",
152                                    "MP_RECV_WHOLE_MSG"};
153static char *transp_dev2string[5] = {"TCP", "FILE", "PVM", "TB", NULL};
154
155static MP_Status_t fill_a_buff _ANSI_ARGS_((MP_Link_pt));
156static MP_Status_t flush_out _ANSI_ARGS_((MP_Link_pt, buffer_handle_pt));
157static MP_Status_t get_input_bytes _ANSI_ARGS_((MP_Link_pt, char *, int));
158static MP_Status_t set_input_fragment _ANSI_ARGS_((MP_Link_pt));
159static MP_Status_t skip_input_bytes _ANSI_ARGS_((MP_Link_pt, long));
160static int         transp_to_num _ANSI_ARGS_((char *transp));
161
162/*
163  Backup the necessary fields of the link message by n bytes.
164  The idea is to restore some field of a packet to the buffer
165  so it can be reread.  This is intended to be used by a tool
166  when it expects one type, but does a read and discovers another
167  type.  There may be a better way to solve this problem.
168  It is assumed that all reads will occur in multiple of four bytes,
169  so a four byte read (or restore) should never cross a buffer fragment
170  boundary. If it does, MP_Failure is returned. Else return MP_Success.
171*/
172
173
174#ifdef __STDC__
175MP_Status_t IMP_Restore(MP_Link_pt link, unsigned long n)
176#else
177MP_Status_t IMP_Restore(link, n)
178    MP_Link_pt     link;
179    unsigned long  n;
180#endif
181{
182   if (n > ((unsigned long)link->in_finger - (unsigned long)link->in_base - 
183            sizeof(long))) {
184    return MP_Failure;
185   }
186   link->fbtbc     += n;
187   link->in_finger -= n;
188
189   return MP_Success;
190}
191
192
193#ifdef __STDC__
194MP_Link_pt MP_OpenLink(MP_Env_pt env, int argc, char **argv)
195#else
196MP_Link_pt MP_OpenLink(env, argc, argv)
197    MP_Env_pt   env;
198    int         argc;
199    char      **argv;
200#endif
201{
202    buffer_handle_pt  cur_buff, old_buff;
203    MP_Link_pt        link;
204    MP_TranspList_pt  tp_ops;
205    int               counter;
206    char             *transp = NULL;
207    int               transp_dev = 0;
208
209#ifdef MP_DEBUG
210    fprintf(stderr, "MP_OpenLink: entering, argc = %d\n", argc);
211#endif
212
213    link = (MP_Link_pt)IMP_MemAllocFnc(sizeof(MP_Link_t));
214
215    if (link == NULL) {
216        fprintf(stderr,
217                "MP_OpenLink: memory allocation error - can't continue\n");
218        fflush(stderr);
219        return NULL;
220    }
221
222    if (env == NULL || !env->initialized) {
223        fprintf(stderr,
224                "MP_OpenLink: MP environment not initialized"
225                " - can't continue\n");
226        fflush(stderr);
227        return NULL;
228    }
229
230    link->env        = env;
231    link->link_id    = ++env->num_links;
232    link->snd_mode   = MP_DEFAULT_SEND_MODE;
233    link->rcv_mode   = MP_DEFAULT_RECV_MODE;
234    link->num_o_buff = 1;
235
236    link->i_buff      = NULL;
237    link->curr_i_buff = NULL;
238
239    link->i_buff      = get_i_buff(link);
240    link->curr_i_buff = link->i_buff;
241
242    if (link->i_buff == NULL)
243        return NULL;
244
245    link->o_buff      = NULL;
246    link->curr_o_buff = NULL;
247
248    link->o_buff      = get_o_buff(link);
249    link->curr_o_buff = link->o_buff;
250
251    if (link->o_buff == NULL)
252        return NULL;
253
254    old_buff = link->o_buff;
255    for (counter = 1; counter < env->num_o_buff; counter++) {
256        cur_buff = get_buffer(env->buff_pool);
257        if (cur_buff != NULL)
258            old_buff = old_buff->next = cur_buff;
259        else
260            return NULL;
261    }
262
263    link->MP_errno    = MP_Success;
264    link->logmask     = MP_LOG_INIT_EVENTS;
265    link->num_o_buff  = counter;
266    link->fbtbc       = 0;
267    link->last_frag   = MP_TRUE;
268    link->s_last_frag = MP_FALSE;
269    link->sfblr       = -1;
270    link->in_boundry  = link->in_finger;
271
272    /* The default to start with, but is negotiable between partners: */
273    link->link_word_order = MP_BigEndian;
274
275    /* Default floating point format is IEEE - this is negotiable: */
276    link->link_fp_format = MP_IEEE_fp;
277
278    link->bignum.bigint_ops   = env->bignum.bigint_ops;
279    link->link_bigint_format  = env->bignum.native_bigint_format;
280    link->bignum.bigreal_ops  = env->bignum.bigreal_ops;
281    link->link_bigreal_format = env->bignum.native_bigreal_format;
282
283
284    if ((transp = IMP_GetCmdlineArg(argc, argv, "-MPtransp")) == NULL) {
285        MP_LogEvent(link, MP_ERROR_EVENT,
286                    "MP_OpenLink: Missing -MPtransp option");
287        return NULL;
288    }
289    transp_dev = transp_to_num(transp);
290
291    if ((tp_ops = IMP_GetTranspByName(env, transp_dev)) == NULL) {
292        msg = (char*) IMP_RawMemAllocFnc(strlen(transp) + 28);
293        sprintf(msg, "Unknown transport device %s", transp);
294        MP_LogEvent(link, MP_ERROR_EVENT, msg);
295        IMP_RawMemFreeFnc(msg);
296        return NULL;
297    }
298
299    if (tp_ops->transp_ops.open_transp(link, argc, argv) != MP_Success) {
300        msg = (char*) IMP_RawMemAllocFnc(strlen(transp) + 46);
301        sprintf(msg, "MP_OpenLink: Couldn't open %s transport device",
302                transp);
303        MP_LogEvent(link, MP_ERROR_EVENT, msg);
304        IMP_RawMemFreeFnc(msg);
305        return NULL;
306    }
307
308#ifndef NO_LOGGING
309    fprintf(env->logfd, "L%d: Application: %s\n", link->link_id, argv[0]);
310    msg = (char*) IMP_RawMemAllocFnc(strlen(transp) + 46);
311    sprintf(msg, "MP_OpenLink: opened link for transport %s",
312            transp);
313    MP_LogEvent(link, MP_INIT_EVENT, msg);
314    IMP_RawMemFreeFnc(msg);
315#endif
316
317#ifdef MP_DEBUG
318    fprintf(stderr, "MP_OpenLink: exiting\n");fflush(stderr);
319#endif
320
321    return link;
322}
323
324
325/********************************************************************
326 * FUNCTION:  MP_CloseLink
327 * ARGUMENT:  link - pointer to a link structure
328 * RETURN:    none
329 * PURPOSE:   Release any buffers associated with the link by
330 *            returning them to the buffer pool and call the
331 *            transport-specific close routine.
332 ********************************************************************/
333#ifdef __STDC__
334void MP_CloseLink(MP_Link_pt link)
335#else
336void MP_CloseLink(link)
337    MP_Link_pt link;
338#endif
339{
340    buffer_handle_pt cur_buff, old_buff;
341
342#ifdef MP_DEBUG
343    fprintf(stderr, "MP_CloseLink: entering for link %d\n", link->link_id);
344#endif
345
346    if (link != NULL) {
347        if ((cur_buff = link->o_buff) == NULL)
348            return;
349
350      /* Check just in case the environment was released first. */
351      /* It shouldn't have been, but you never know.            */
352      if (link->env == NULL) {
353        fprintf(stderr, "MP_CloseLink: NULL environment pointer!!\n");
354        return;
355      }
356
357
358        while (cur_buff != NULL) {
359            old_buff = cur_buff;
360            cur_buff = old_buff->next;
361            free_buffer(link->env->buff_pool, old_buff);
362        }
363
364        if ((cur_buff = link->i_buff) == NULL)
365            return;
366
367        while (cur_buff != NULL) {
368            old_buff = cur_buff;
369            cur_buff = old_buff->next;
370            free_buffer(link->env->buff_pool, old_buff);
371        }
372        link->transp.transp_ops->close_transp(link);
373
374#ifndef NO_LOGGING
375        if (link->logmask & MP_LOG_INIT_EVENTS)
376            MP_LogEvent(link, MP_INIT_EVENT, "MP_CloseLink: closed link\n");
377#endif
378
379        IMP_MemFreeFnc(link, sizeof(MP_Link_t));
380    }
381
382#ifdef MP_DEBUG
383    fprintf(stderr, "MP_CloseLink: exiting\n");
384#endif
385
386    return;
387}
388
389#ifdef __STDC__
390void MP_KillLink(MP_Link_pt link)
391#else
392void MP_KillLink(link)
393    MP_Link_pt link;
394#endif
395{
396    buffer_handle_pt cur_buff, old_buff;
397
398#ifdef MP_DEBUG
399    fprintf(stderr, "MP_KillLink: entering for link %d\n", link->link_id);
400#endif
401
402    if (link != NULL) {
403        if ((cur_buff = link->o_buff) == NULL)
404            return;
405
406      /* Check just in case the environment was released first. */
407      /* It shouldn't have been, but you never know.            */
408      if (link->env == NULL) {
409        fprintf(stderr, "MP_KillLink: NULL environment pointer!!\n");
410        return;
411      }
412
413
414        while (cur_buff != NULL) {
415            old_buff = cur_buff;
416            cur_buff = old_buff->next;
417            free_buffer(link->env->buff_pool, old_buff);
418        }
419
420        if ((cur_buff = link->i_buff) == NULL)
421            return;
422
423        while (cur_buff != NULL) {
424            old_buff = cur_buff;
425            cur_buff = old_buff->next;
426            free_buffer(link->env->buff_pool, old_buff);
427        }
428        link->transp.transp_ops->kill_transp(link);
429
430#ifndef NO_LOGGING
431        if (link->logmask & MP_LOG_INIT_EVENTS)
432            MP_LogEvent(link, MP_INIT_EVENT, "MP_KillLink: closed link\n");
433#endif
434
435        IMP_MemFreeFnc(link, sizeof(MP_Link_t));
436    }
437
438#ifdef MP_DEBUG
439    fprintf(stderr, "MP_KillLink: exiting\n");
440#endif
441
442    return;
443}
444
445
446
447/********************************************************************
448 * FUNCTION:  MP_GetLinkStatus
449 * ARGUMENT:  link - pointer to a link structure
450 * RETURN:    true - the status request checked is valid
451 *            false - status request checked is not valid
452 *
453 * PURPOSE:   Determine if the requested status check is valid or not
454 *            for the given link.
455 * NOTES:     For some devices this will be a meaningless test?
456 *            They should return MP_False and print an error message
457 *            to the logfile.
458 ********************************************************************/
459#ifdef __STDC__
460MP_Boolean_t MP_GetLinkStatus(MP_Link_pt      link,
461                              MP_LinkStatus_t status_to_check)
462#else
463MP_Boolean_t MP_GetLinkStatus(link, status_to_check)
464    MP_Link_pt      link;
465    MP_LinkStatus_t status_to_check;
466#endif
467{
468    return link->transp.transp_ops->get_status(link, status_to_check);
469}
470
471/********************************************************************
472 * FUNCTION:  MP_EndMsgReset
473 * ARGUMENTS: link - (in) pointer to a link structure
474 * RETURN:    success - MP_Success
475 *            failure - MP_Failure
476 * PURPOSE:   Combine the MP_EndMsg() and MP_ResetLink() operations.
477 *            This was formerly done using a macro, but we ran into
478 *            trouble when people wanted to do
479 *            return(MP_EndMsgReset(link)), which only executed the
480 *            first of the two operations.
481 ********************************************************************/
482#ifdef __STDC__
483MP_Status_t MP_EndMsgReset(MP_Link_pt link)
484#else
485MP_Status_t MP_EndMsgReset(link)
486    MP_Link_pt link;
487#endif
488{
489    ERR_CHK(MP_EndMsg(link));
490    ERR_CHK(MP_ResetLink(link));
491
492    return MP_ClearError(link);
493}
494
495/********************************************************************
496 * FUNCTION:  MP_PeekHeader
497 * ARGUMENTS: link - (in) pointer to a link structure
498 *            ntype - (out) value from type field of node pkt hdr
499 *            cval  - (out) value from common value field of node pkt hdr
500 *            dtag  - (out) value from dictionary tag field of node pkt hdr
501 * RETURN:    success - MP_Success
502 *            failure - MP_Failure
503 *
504 * PURPOSE:   Read in the next node packet header and extract the
505 *            type, common value and dictionary tag fields.  Then
506 *            back up in the read buffer to restore the node pkt hdr
507 *            so the application can reread it.
508 * NOTES:     The 4 bytes read aren't guaranteed to be meaningful.
509 *            It is assumed that the next 4 bytes really are a node
510 *            packet header. One aspect of dealing with a binary
511 *            encoding is that we can't be certain what the bits really
512 *            are.
513 ********************************************************************/
514
515#ifdef __STDC__
516MP_Status_t MP_PeekHeader(MP_Link_pt     link,
517                          MP_NodeType_t *ntype,
518                          MP_DictTag_t  *dtag,
519                          MP_Common_t   *cval)
520#else
521MP_Status_t MP_PeekHeader(link, ntype, dtag, cval)
522    MP_Link_pt     link;
523    MP_NodeType_t *ntype;
524    MP_DictTag_t  *dtag;
525    MP_Common_t   *cval;
526#endif
527{
528    MP_NodeHeader_t hdr;
529
530    ERR_CHK(IMP_GetLong(link, (long*)&hdr));
531    ERR_CHK(IMP_Restore(link, sizeof(MP_NodeHeader_t)));
532
533    *ntype = MP_GetNodeFieldType(hdr);
534    *cval  = MP_GetNodeCommonValueField(hdr);
535    *dtag  = MP_GetNodeDictTagField(hdr);
536
537    return MP_Success;
538}
539
540
541/********************************************************************
542 * FUNCTION:  MP_SetLinkOption
543 * ARGUMENT:  link   - (in) pointer to a link structure
544 *            option - (in) the option to set
545 *            value  - (in) value to set the option to
546 * RETURN:    success - old value of the option
547 *            failure - MP_Failure
548 *
549 * PURPOSE:   Make sure that the option and value are valid.  For
550 *            the log mask option, we don't do this and trust the
551 *            user to not do something stupid.
552 ********************************************************************/
553#ifdef __STDC__
554int MP_SetLinkOption(MP_Link_pt link,
555                     int        option,
556                     int        value)
557#else
558int MP_SetLinkOption(link, option, value)
559    MP_Link_pt link;
560    int        option;
561    int        value;
562#endif
563{
564    int oldval = 0;
565
566    if (link == NULL) {
567        fprintf(stderr, "MP_SetLinkOption: null link!!\n");
568        fflush(stderr);
569        return MP_Failure;
570    }
571
572    switch (option) {
573    case MP_LINK_SEND_MODE_OPT:
574        oldval = link->snd_mode;
575        if (value != MP_SEND_WHOLE_MSG && value != MP_SEND_FRAG_MSG) {
576            MP_LogEvent(link, MP_ERROR_EVENT,
577                        "MP_SetLinkOption: "
578                        "illegal option value for link send mode");
579            return MP_Failure;
580        }
581        sprintf(log_msg, "%s %s", "MP_SetLinkOption: set Send Mode to",
582                send_mode2string[value - 1]);
583        link->snd_mode = value;
584        break;
585
586    case MP_LINK_RECV_MODE_OPT:
587        oldval = link->rcv_mode;
588        if (value != MP_RECV_WHOLE_MSG && value != MP_RECV_FRAG_MSG_SENDER
589            && value != MP_RECV_FRAG_MSG_RECVER) {
590            MP_LogEvent(link, MP_ERROR_EVENT,
591                        "MP_SetLinkOption: "
592                        "illegal option value for link receive mode");
593            return MP_Failure;
594        }
595        sprintf(log_msg, "%s %s", "MP_SetLinkOption: set Receive Mode to",
596                recv_mode2string[value - 1]);
597        link->rcv_mode = value;
598        break;
599
600    case MP_LINK_LOG_MASK_OPT:
601        oldval = link->logmask;
602        switch (value) {
603        case MP_LOG_READ_EVENTS:
604        case MP_LOG_WRITE_EVENTS:
605        case MP_LOG_INIT_EVENTS:
606        case MP_LOG_CONTROL_EVENTS:
607        case MP_LOG_URGENT_EVENTS:
608        case MP_LOG_ALL_EVENTS:
609            link->logmask |= value;
610            break;
611
612        case MP_LOG_NO_READ_EVENTS:
613        case MP_LOG_NO_WRITE_EVENTS:
614        case MP_LOG_NO_INIT_EVENTS:
615        case MP_LOG_NO_CONTROL_EVENTS:
616        case MP_LOG_NO_URGENT_EVENTS:
617        case MP_LOG_NO_EVENTS:
618            link->logmask &= value;
619            break;
620
621        default:
622            sprintf(log_msg, "MP_SetLinkOption: bad logmask - 0x%X", value);
623            MP_LogEvent(link, MP_ERROR_EVENT, log_msg);
624            return MP_Failure;
625        }
626        sprintf(log_msg, "MP_SetLinkOption: set logmask to 0x%X",
627                link->logmask);
628        break;
629
630    default:
631        sprintf(log_msg, "MP_SetLinkOption: illegal option - 0x%X", option);
632        MP_LogEvent(link, MP_ERROR_EVENT, log_msg);
633        return MP_Failure;
634    }
635
636#ifndef NO_LOGGING
637    if (link->logmask & MP_LOG_INIT_EVENTS)
638        MP_LogEvent(link, MP_INIT_EVENT, log_msg);
639#endif
640
641    return oldval;
642}
643
644/********************************************************************
645 * FUNCTION:  MP_GetLinkOption
646 * ARGUMENT:  link   - (in) pointer to a link structure
647 *            option - (in) the option to return
648 * RETURN:    success - value of the option
649 *            failure - MP_Failure
650 *
651 * PURPOSE:   Make sure that the option is valid.
652 * NOTE:      Since we return MP_Failure for an illegal option, we
653 *            must make sure that there can never be a legal option
654 *            value of 0 (MP_Failure).
655 ********************************************************************/
656#ifdef __STDC__
657int MP_GetLinkOption(MP_Link_pt link, int option)
658#else
659int MP_GetLinkOption(link, option)
660    MP_Link_pt link;
661    int        option;
662#endif
663{
664    if (link == NULL) {
665        fprintf(stderr, "MP_GetLinkOption: null link!!\n");
666        fflush(stderr);
667        return MP_Failure;
668    }
669
670    switch (option) {
671    case MP_LINK_SEND_MODE_OPT:
672        return link->snd_mode;
673    case MP_LINK_RECV_MODE_OPT:
674        return link->rcv_mode;
675    case MP_LINK_LOG_MASK_OPT:
676        return link->logmask;
677    default:
678        MP_LogEvent(link, MP_ERROR_EVENT,  "MP_GetLinkOption: illegal option");
679    }
680
681    return MP_Failure;
682}
683
684
685/*
686 * IMP_GetLong() fetches a long integer from a link and store it in lp.
687 * returns either MP_Success or MP_Failure.
688 * arguments:
689 *     link: the link from which the long integer is to be fetched.
690 *     lp: pointer to memory location where the long integer is to be stored.
691 */
692#ifdef __STDC__
693MP_Status_t IMP_GetLong(MP_Link_pt  link,
694                        long       *lp)
695#else
696MP_Status_t IMP_GetLong(link, lp)
697    MP_Link_pt  link;
698    long       *lp;
699#endif
700{
701    long mylong, *buflp = (long *)link->in_finger;
702
703#ifdef MP_DEBUG
704    fprintf(stderr, "IMP_GetLong: entering\n");
705#endif
706
707    /* first try the inline, fast case */
708    if (link->fbtbc >= sizeof(long)
709        && (int)link->in_boundry - (int)buflp >= sizeof(long)) {
710
711#ifdef WORDS_BIGENDIAN
712        *lp = *buflp;
713#else /* not WORDS_BIGENDIAN */
714        /*
715         * Ooh-argh! The following may be problematic if we are doing the
716         * conversion on the SOURCE (the buffer).  If the programmer backs
717         * up in the buffer and then rereads this data, what is the result?
718         * The bytes will have been moved around!
719         */
720
721        if (link->link_word_order == MP_BigEndian)
722            *lp = (long)ntohl((unsigned long)(*buflp));
723        else
724            *lp = *buflp;
725#endif /* not WORDS_BIGENDIAN */
726
727        link->fbtbc     -= sizeof(long);
728        link->in_finger += sizeof(long);
729    } else {
730        if (!IMP_GetBytes(link, (char *)&mylong, sizeof(long)))
731            return MP_Failure;
732
733#ifdef WORDS_BIGENDIAN
734        *lp = mylong;
735#else /* not WORDS_BIGENDIAN */
736        if (link->link_word_order == MP_BigEndian)
737            *lp = (long)ntohl((unsigned long)mylong);
738        else
739            *lp = mylong;
740#endif /* not WORDS_BIGENDIAN */
741    }
742
743#ifdef MP_DEBUG
744    fprintf(stderr, "IMP_GetLong: exiting successfully, returning 0x%X\n", *lp);
745#endif
746
747    return MP_Success;
748}
749
750
751/*
752 * IMP_PutLong() puts a long integer from lp to a link.
753 * returns either MP_Success or MP_Failure.
754 * arguments:
755 *     link: the link to which the long integer is to be put.
756 *     lp: pointer to memory location where the long integer is stored.
757 */
758
759#ifdef __STDC__
760MP_Status_t IMP_PutLong(MP_Link_pt  link,
761                        long       *lp)
762#else
763MP_Status_t IMP_PutLong(link, lp)
764    MP_Link_pt  link;
765    long       *lp;
766#endif
767{
768#ifdef MP_DEBUG
769    fprintf(stderr, "IMP_PutLong: entering - long is %d, 0x%X\n", *lp, *lp);
770#endif
771
772    if (link->out_finger + sizeof(long) > link->out_boundry) {
773        *(link->o_frag_header) = (unsigned long)link->out_finger
774                                 - (unsigned long)link->o_frag_header - sizeof(unsigned long);
775        if (link->snd_mode) {
776            if (!flush_out(link,link->o_buff))
777                return MP_Failure;
778            MP_ResetLink(link);
779        }
780        else {
781            link->curr_o_buff = get_o_buff(link);
782            if (link->curr_o_buff == NULL)
783                return MP_Failure;
784        }
785    }
786
787#ifdef WORDS_BIGENDIAN
788    *(long *)link->out_finger = (long)*lp;
789#else /* not WORDS_BIGENDIAN */
790    /*
791     * I am a little endian machine - see if I have to use big-endian
792     * to satisfy my partner
793     */
794    if (link->link_word_order == MP_BigEndian)
795        *(long *)link->out_finger = (long)htonl((unsigned long)(*lp));
796    else
797        *(long *)link->out_finger = *lp;
798#endif /* not WORDS_BIGENDIAN */
799
800    link->out_finger += sizeof(long);
801
802#ifdef MP_DEBUG
803    fprintf(stderr, "IMP_PutLong: exiting successfully - put 0x%X\n", *lp);
804#endif
805
806    return MP_Success;
807
808}
809
810
811/*
812 * IMP_GetBytes() fetches a given number of bytes from a link.
813 * returns either MP_Success or MP_Failure.
814 * arguments:
815 *     link: the link from which the bytes are fetched.
816 *     addr: pointer to memory location in which the bytes are to be stored.
817 *     len: number of bytes to be fetched.
818 * must manage buffers, fragments, and messages
819 */
820
821#ifdef __STDC__
822MP_Status_t  IMP_GetBytes(MP_Link_pt    link,
823                          char *       addr,
824                          unsigned long len)
825#else
826MP_Status_t  IMP_GetBytes(link, addr, len)
827    MP_Link_pt    link;
828    char *       addr;
829    unsigned long len;
830#endif
831{
832    unsigned long current;
833
834#ifdef MP_DEBUG
835    fprintf(stderr, "IMP_GetBytes: entering - len = %u, addr = 0x%X\n",
836            len, addr);
837    fprintf(stderr, "IMP_GetBytes: entering - last_frag = %d, fbtbc = %d\n",
838            link->last_frag, link->fbtbc);
839#endif
840
841    while (len > 0) {
842        current = link->fbtbc;
843        if (current == 0) {
844            if (link->last_frag || !set_input_fragment(link))
845                return MP_Failure;
846        } else {
847            current = (len < current) ? len : current;
848            if (!get_input_bytes(link, addr, current))
849                return MP_Failure;
850
851            addr        += current;
852            link->fbtbc -= current;
853            len         -= current;
854        }
855    }
856
857#ifdef MP_DEBUG
858    fprintf(stderr, "IMP_GetBytes: exiting - addr = 0x%X\n", addr);
859#endif
860
861    return MP_Success;
862}
863
864/*
865 * IMP_PutBytes() puts a given number of bytes into a link.
866 * returns either MP_Success or MP_Failure.
867 * arguments:
868 *     link: the link into which the bytes are put.
869 *     addr: pointer to memory location in which the bytes are stored.
870 *     len: number of bytes to put.
871 */
872
873#ifdef __STDC__
874MP_Status_t IMP_PutBytes(MP_Link_pt    link,
875                         char *       addr,
876                         unsigned long len)
877#else
878MP_Status_t IMP_PutBytes(link, addr, len)
879    MP_Link_pt    link;
880    char *       addr;
881    unsigned long len;
882#endif
883{
884    unsigned long current;
885
886#ifdef MP_DEBUG
887    printf("IMP_PutBytes: entering - len = %d, addr = %X\n", len, addr);
888#endif
889
890    while (len > 0) {
891        current = (unsigned long)link->out_boundry - (unsigned long)link->out_finger;
892        current = (len < current) ? len : current;
893        memcpy(link->out_finger, addr, current);
894
895        link->out_finger += current;
896        addr             += current;
897        len              -= current;
898
899        if (link->out_finger == link->out_boundry) {
900            *(link->o_frag_header) = (unsigned long)link->out_finger
901                                     - (unsigned long)link->o_frag_header
902                                     - sizeof(unsigned long);
903            if (link->snd_mode) {
904                if (!flush_out(link, link->o_buff))
905                    return MP_Failure;
906                MP_ResetLink(link);
907            }
908            else
909                if (len <= 0)
910                    return MP_Success;
911                else {
912                    link->curr_o_buff = get_o_buff(link);
913                    if (link->curr_o_buff == NULL)
914                        return MP_Failure;
915                }
916
917        }
918    }
919
920#ifdef MP_DEBUG
921    printf("IMP_PutBytes: exiting\n");
922#endif
923
924    return MP_Success;
925}
926
927
928/*
929 * MP_SkipMsg() skips all data in current message.
930 * Before reading (deserializing from the link), one should always call
931 * this procedure to guarantee proper message alignment.
932 * MP_SkipMsg() does not cause the link to read in a buffer upon first
933 * call.
934 * returns either MP_Success or MP_Failure.
935 * arguments:
936 *     link: the link to be processed by MP_SkipMsg().
937 */
938#ifdef __STDC__
939MP_Status_t MP_InitMsg(MP_Link_pt link)
940#else
941MP_Status_t MP_InitMsg(link)
942    MP_Link_pt link;
943#endif
944{
945#ifdef MP_DEBUG
946    fprintf(stderr, "MP_InitMsg: entering - fbtbc = %u, last_frag = %u\n",
947            link->fbtbc, link->last_frag);
948#endif
949
950#ifndef NO_LOGGING
951    if (link->logmask & MP_LOG_READ_EVENTS) {
952        sprintf(log_msg,
953                "MP_InitMsg: %lu bytes left in previous fragment, "
954                "last fragment bit is %s",
955                link->fbtbc, (link->last_frag) ? "TRUE" : "FALSE");
956        MP_LogEvent(link, MP_READ_EVENT, log_msg);
957    }
958#endif
959    if (link->fbtbc > 0 || link->last_frag)
960        ERR_CHK(MP_SkipMsg(link)); 
961    if(!set_input_fragment(link))
962      return MP_SetError(link, MP_CantInitMsg);
963
964    return MP_ClearError(link);
965}
966
967
968#ifdef __STDC__
969MP_Status_t MP_SkipMsg(MP_Link_pt link)
970#else
971MP_Status_t MP_SkipMsg(link)
972    MP_Link_pt link;
973#endif
974{
975#ifdef MP_DEBUG
976    fprintf(stderr, "MP_SkipMsg: entering - fbtbc = %u, last_frag = %u\n",
977            link->fbtbc, link->last_frag);
978#endif
979
980#ifndef NO_LOGGING
981    if (link->logmask & MP_LOG_READ_EVENTS) {
982        sprintf(log_msg,
983                "MP_SkipMsg: %lu bytes left in previous fragment, "
984                "last fragment bit is %s",
985                link->fbtbc, (link->last_frag) ? "TRUE" : "FALSE");
986        MP_LogEvent(link, MP_READ_EVENT, log_msg);
987    }
988#endif
989
990    if (link == NULL || link->env == NULL) return MP_NullLink;
991    while (link->fbtbc > 0 || !link->last_frag) {
992        if (!skip_input_bytes(link, link->fbtbc))
993            return MP_SetError(link, MP_CantSkipMsg);
994
995        link->fbtbc = 0;
996        if (!link->last_frag && !set_input_fragment(link))
997            return MP_SetError(link, MP_CantSkipMsg);
998    }
999
1000    link->last_frag  = MP_FALSE;
1001    m_free_in_bufs(link);
1002    link->in_boundry = link->in_finger;
1003    link->sfblr      = -1;
1004
1005#ifdef MP_DEBUG
1006    fprintf(stderr, "MP_SkipMsg: exiting - fbtbc = %u, last_frag = %u\n",
1007            link->fbtbc, link->last_frag);
1008#endif
1009
1010    return MP_ClearError(link);
1011}
1012
1013
1014
1015/*
1016 * MP_EndMsg() signifies the end of an MP message. It sets the proper header
1017 * information in the buffer and initiates a flush to send the buffer(s).
1018 * The client must tell the package when an end-of-message has occurred.
1019 * returns either MP_Success or MP_Failure
1020 * argument:
1021 *     link: the link in which end of message occurrs.
1022 */
1023
1024#ifdef __STDC__
1025MP_Status_t MP_EndMsg(MP_Link_pt link)
1026#else
1027MP_Status_t MP_EndMsg(link)
1028    MP_Link_pt link;
1029#endif
1030{
1031    buffer_handle_pt cur_buff;
1032
1033    if (link == NULL)
1034        return MP_Failure;
1035
1036    /*
1037     * the problem here is that o_frag_header appears not to have been
1038     * set to the beginning of the current buffer, pointed to by
1039     * cur_buff->buff.  So the eor bit does not get set properly.
1040     */
1041
1042    *(long*)link->o_frag_header = ((unsigned long)link->out_finger
1043                                   - (unsigned long)link->o_frag_header
1044                                   - sizeof(long)) | eor_mask;
1045
1046    cur_buff = link->o_buff;
1047    while ((*(long *)cur_buff->buff & eor_mask) == 0) {
1048        if (!flush_out(link, cur_buff))
1049            return MP_Failure;
1050        cur_buff = cur_buff->next;
1051    }
1052
1053    if (!flush_out(link, cur_buff))
1054        return MP_Failure;
1055
1056#ifndef NO_LOGGING
1057    if (link->logmask & MP_LOG_WRITE_EVENTS)
1058        MP_LogEvent(link, MP_WRITE_EVENT, "MP_EndMsg: end of message");
1059#endif
1060
1061#ifdef MP_DEBUG
1062    fprintf(stderr,"MP_EndMsg: exiting\n");
1063#endif
1064
1065    return MP_Success;
1066}
1067
1068
1069/*******************************************************************************
1070 *
1071 * Internal useful routines
1072 *
1073 ******************************************************************************/
1074
1075#ifdef __STDC__
1076static MP_Status_t flush_out(MP_Link_pt       link,
1077                             buffer_handle_pt buff)
1078#else
1079static MP_Status_t flush_out(link, buff)
1080    MP_Link_pt       link;
1081    buffer_handle_pt buff;
1082#endif
1083{
1084    unsigned long len, hdr;
1085
1086    /*
1087     * QUESTION: Has the end-of-message bit been set by the time we get here?
1088     *      Yes, in MP_EndMsg()
1089     */
1090
1091    if (buff == NULL || buff->buff == NULL)
1092        return MP_Failure;
1093
1094    len = (*(long *)buff->buff & ~eor_mask) + sizeof(long);
1095    hdr = *(unsigned long *)buff->buff;
1096    *(long *)buff->buff = htonl(hdr);
1097
1098    if (link->transp.transp_ops->write_buf(link, buff->buff, len) != len)
1099        return MP_Failure;
1100
1101    if (link->transp.transp_ops->flush_buf(link) != MP_Success) {
1102        fprintf(stderr,"flush_out: failed on flush_buf\n"); fflush(stderr);
1103        return MP_Failure;
1104        }
1105
1106#ifdef MP_DEBUG
1107    fprintf(stderr, "flush_out: exiting, len = %d, hdr = 0x%X\n",
1108            len, htonl(hdr));
1109    fflush(stderr);
1110#endif
1111
1112    return MP_Success;
1113}
1114
1115
1116#ifdef __STDC__
1117MP_Boolean_t MP_TestEofMsg(MP_Link_pt link)
1118#else
1119MP_Boolean_t MP_TestEofMsg(link)
1120    MP_Link_pt link;
1121#endif
1122{
1123    if (link == NULL) {
1124        fprintf(stderr, "MP_TestEofMsg: NULL link!\n");
1125        fflush(stderr);
1126        return MP_TRUE;
1127    }
1128
1129    if (link->fbtbc == 0 && link->last_frag)
1130        return MP_TRUE;
1131
1132    return MP_FALSE;
1133}
1134
1135
1136int transp_to_num(char *transp)
1137{
1138   int i = 0;
1139   while (transp_dev2string[i] != NULL &&
1140          strcmp(transp, transp_dev2string[i]) != 0) i++;
1141   return i;
1142
1143}
1144
1145/*
1146 * fill_a_buff() fills a reciever's buffer. It quits when a recievers' buffer
1147 * is full, or when it has reached the end of a message.
1148 * This function is called internally by fill_input_buf().
1149 */
1150#ifdef __STDC__
1151static MP_Status_t fill_a_buff(MP_Link_pt link)
1152#else
1153static MP_Status_t fill_a_buff(link)
1154  MP_Link_pt link;
1155#endif
1156{
1157    unsigned long bytes_to_read, bytes_read, bytes_left;
1158    unsigned long hdr;
1159
1160#ifdef MP_DEBUG
1161    fprintf(stderr, "fill_a_buff: entering\n");
1162    fprintf(stderr, "\t\tin_boundry = 0x%X, in_finger = 0x%X\n", 
1163            link->in_boundry, link->in_finger); 
1164#endif
1165
1166    for ( ; ; ) {
1167        bytes_read = link->transp.transp_ops->read_buf(link, &hdr,
1168                                                       sizeof(long));
1169        if (bytes_read != sizeof(long)) {
1170            /* March 11  sgray - added the following so that repeated
1171               attempts to read from an empty data stream (e.g., an
1172               empty file) would fail.  Before this, a first attempt
1173               to read would fail but subsequent attempts would think
1174               there was data in the link because m_free_in_bufs(),
1175               invoked in fill_input_buf(), resets these two pointers
1176               to be the beginning (in_finger) and end (in_boundry) of
1177               an input buffer.  Other routines rely on this to know
1178               how much space there is to put data. */
1179            link->in_boundry = link->in_finger;
1180            return MP_Failure;
1181            }
1182
1183        hdr = ntohl(hdr);
1184        link->s_last_frag = (hdr & eor_mask) == 0 ? MP_FALSE : MP_TRUE;
1185        hdr = hdr & ~eor_mask;
1186        link->sfblr = hdr;
1187
1188        /*  sometimes the link seems ready and the read routine returns, but  */
1189        /*  nothing was actually read and we return as if everything is okay! */
1190        /*  if (link->sfblr == 0) return(MP_Failure);                        */
1191        /*  I commented out the line above so that we could handle the      */
1192        /*  special case in which the amount of data sent is exactly the    */
1193        /*  buffer size. In this case, the sender calls MP_EndMsg() which   */
1194        /*  sends an _empty_ buffer (0 bytes) but with the eor bit set.     */
1195        /*  We want to read in that 4 byte message fragment header, and     */
1196        /*  handle it properly.  Returning MP_Failure, as the line above    */
1197        /*  did, is clearly wrong.  I do not remember clearly why I         */
1198        /*  put that line in.  We'll see what happens :-)                   */
1199
1200        while (link->sfblr != 0) {
1201            if (link->in_finger == link->in_boundry) {
1202                link->in_finger = link->in_base;
1203                return MP_Success;
1204            }
1205
1206            bytes_left    = (unsigned long)link->in_boundry - (unsigned long)link->in_finger;
1207            bytes_to_read = link->sfblr < bytes_left ? link->sfblr : bytes_left;
1208            bytes_read    = link->transp.transp_ops->read_buf(link,
1209                                                              link->in_finger,
1210                                                              bytes_to_read);
1211
1212            link->in_finger      += bytes_read;
1213            *link->i_frag_header += bytes_read;
1214            link->sfblr          -= bytes_read;
1215        }
1216
1217        if (link->s_last_frag) {
1218            *link->i_frag_header = *link->i_frag_header | eor_mask;
1219            link->in_finger      = link->in_base;
1220            return MP_Success;
1221        }
1222    }
1223
1224#ifdef MP_DEBUG
1225    fprintf(stderr, "fill_a_buff: exiting\n");
1226    fflush(stderr);
1227#endif
1228}
1229
1230
1231/******************************************************************************
1232 *
1233 * fill_input_buf() does the following:
1234 * 1. Depending on rcv_mode, it reads in an appropriate amount of data
1235 *    into reciever's buffers.
1236 * 2. It prepares the pointers in the input links for other routines
1237 *    that read data from the input buffers.
1238 * This routine manages both message and fragment.
1239 * returns either MP_Success or MP_Failure.
1240 *
1241 ******************************************************************************/
1242#ifdef __STDC__
1243MP_Status_t fill_input_buf(MP_Link_pt link)
1244#else
1245MP_Status_t fill_input_buf(link)
1246    MP_Link_pt link;
1247#endif
1248{
1249    unsigned long  bytes_to_read, bytes_read, bytes_left, eor, x, xx;
1250    unsigned long  tmp_int, hdr;
1251
1252#ifdef MP_DEBUG
1253    fprintf(stderr, "fill_input_buf: entering\n");
1254    fprintf(stderr, "\t\tin_boundry = 0x%X, in_finger = 0x%X\n", link->in_boundry, link->in_finger); 
1255#endif
1256
1257    if (link == NULL || link->curr_i_buff == NULL)
1258        return MP_Failure;
1259
1260    if (link->curr_i_buff->next == NULL) {
1261
1262        /* This means we've exhausted all read data, have to read some more. */
1263        /* First thing to do is to get rid of all data read previously. */
1264        m_free_in_bufs(link);
1265
1266        /* Then determine in what fashion we're going to read in new data. */
1267        switch (link->rcv_mode) {
1268        case MP_RECV_FRAG_MSG_RECVER:
1269
1270#ifdef MP_DEBUG
1271            fprintf(stderr, "\tMSG_RECVER: sfblr = %d\n", link->sfblr);
1272#endif
1273
1274            if (link->sfblr > 0 ) {
1275                bytes_to_read = link->sfblr < link->env->buff_pool->buff_size ?
1276                                link->sfblr : link->env->buff_pool->buff_size;
1277
1278                bytes_read = link->transp.transp_ops->read_buf(link,
1279                                                               link->in_finger,
1280                                                               bytes_to_read);
1281                link->in_finger      += bytes_read;
1282                link->sfblr          -= bytes_read;
1283                *link->i_frag_header  = bytes_read;
1284
1285                if (bytes_read != bytes_to_read) {
1286                    link->in_boundry  = link->in_finger;
1287                    link->in_finger  -= bytes_read;
1288                    return MP_Failure;
1289                }
1290
1291                if (link->sfblr == 0)
1292                    if (link->s_last_frag)
1293                        *link->i_frag_header = *link->i_frag_header | eor_mask;
1294                    else
1295                        return fill_a_buff(link);
1296
1297                link->in_finger = link->in_base;
1298                return MP_Success;
1299            }
1300            else
1301                return fill_a_buff(link);
1302
1303
1304        case MP_RECV_FRAG_MSG_SENDER:
1305        case MP_RECV_WHOLE_MSG:
1306
1307#ifdef MP_DEBUG
1308            fprintf(stderr, "\tMSG_SENDER/WHOLE_MSG: sfblr = %d\n",
1309                    link->sfblr);
1310#endif
1311
1312            if (link->sfblr < 0)
1313                link->in_boundry = link->in_finger
1314                                   + link->env->buff_pool->buff_size;
1315            for ( ; ; ) {
1316                bytes_read = link->transp.transp_ops->read_buf(link, &hdr,
1317                                                               sizeof(long));
1318                if (bytes_read != sizeof(long)) {
1319                  if (link->sfblr < 0) link->in_boundry = link->in_finger;
1320                    return MP_Failure;
1321                    }
1322
1323                /*
1324                 * There was no conversion of the header from network to host
1325                 * long!!  August 4, 1995
1326                 */
1327
1328                hdr = ntohl(hdr);
1329                eor = (hdr & eor_mask) == 0 ? MP_FALSE : MP_TRUE;
1330                hdr = hdr & ~eor_mask;
1331                x = hdr;
1332
1333                while (x != 0) {
1334                    if (link->in_finger == link->in_boundry) {
1335                        link->curr_i_buff = get_i_buff(link);
1336                        if (link->curr_i_buff == NULL)
1337                            return MP_Failure;
1338                    }
1339
1340                    bytes_left = (unsigned int)link->in_boundry
1341                                 - (unsigned int)link->in_finger;
1342                    xx = x < bytes_left ? x : bytes_left;
1343                    bytes_read = link->transp.transp_ops->read_buf(link,
1344                                                           link->in_finger, xx);
1345                    link->in_finger      += bytes_read;
1346                    *link->i_frag_header += bytes_read;
1347                    x -= bytes_read;
1348                }
1349
1350                if (eor) {
1351                    *link->i_frag_header = *link->i_frag_header | eor_mask;
1352                    break;
1353                }
1354
1355                if (link->rcv_mode == MP_RECV_FRAG_MSG_SENDER)
1356                    break;
1357            }
1358
1359            link->curr_i_buff->next = NULL; /* supposedly guaranteed */
1360            reset_i_buff(link);
1361
1362#ifdef MP_DEBUG
1363            fprintf(stderr, "fill_input_buf: exiting "
1364                    "- MP_RECV_FRAG_MSG_SENDER/MP_RECV_WHOLE_MSG\n");
1365#endif
1366            return MP_Success;
1367
1368        default:
1369            return MP_Failure;
1370        }
1371    }
1372    else {
1373        link->curr_i_buff   = link->curr_i_buff->next;
1374        link->in_base       = link->curr_i_buff->buff;
1375        link->in_finger     = link->in_base;
1376        link->i_frag_header = (unsigned long *)link->in_base;
1377        tmp_int             = *link->i_frag_header;
1378        link->in_boundry    = link->in_finger + (tmp_int & ~eor_mask)
1379                              + sizeof(long);
1380    }
1381
1382    return MP_Success;
1383}
1384
1385
1386
1387/*******************************************************************************
1388 *
1389 * knows nothing about messages! Only about input buffers
1390 *
1391 *******************************************************************************/
1392#ifdef __STDC__
1393static MP_Status_t  get_input_bytes(MP_Link_pt link,
1394                                    char *    addr,
1395                                    int        len)
1396#else
1397static MP_Status_t  get_input_bytes(link, addr, len)
1398    MP_Link_pt link;
1399    char *    addr;
1400    int        len;
1401#endif
1402{
1403    int current;
1404
1405#ifdef MP_DEBUG
1406    fprintf(stderr, "get_input_bytes: entering - len = %u, addr = 0x%X\n",
1407            len, addr);
1408#endif
1409
1410    while (len > 0) {
1411        current = (int)link->in_boundry - (int)link->in_finger;
1412        if (current == 0) {
1413            if (!fill_input_buf(link))
1414                return MP_Failure;
1415        } else {
1416            current = len < current ? len : current;
1417            memcpy(addr, link->in_finger, current);
1418            link->in_finger += current;
1419            addr            += current;
1420            len             -= current;
1421        }
1422    }
1423
1424#ifdef MP_DEBUG
1425    fprintf(stderr, "get_input_bytes: exiting - addr = 0x%X\n", addr);
1426#endif
1427
1428    return MP_Success;
1429}
1430
1431
1432/*******************************************************************************
1433 *
1434 * next two bytes of the input link are treated as a header
1435 *
1436 *******************************************************************************/
1437#ifdef __STDC__
1438static MP_Status_t set_input_fragment(MP_Link_pt link)
1439#else
1440static MP_Status_t set_input_fragment(link)
1441    MP_Link_pt link;
1442#endif
1443{
1444    unsigned long header;
1445
1446#ifdef MP_DEBUG
1447    fprintf(stderr, "set_input_fragment: entering\n");
1448#endif
1449
1450    if (!get_input_bytes(link, (char *)&header, sizeof(unsigned long)))
1451        return MP_Failure;
1452
1453    /*
1454     * Unfortunately we also have to use ntohl in fill_input_buf, so we
1455     * can't do it here also.  It must be done in one place only!!
1456     */
1457
1458    /* header = (long)ntohl(header); */
1459    link->last_frag = (header & eor_mask) == 0 ? MP_FALSE : MP_TRUE;
1460    link->fbtbc = header & ~eor_mask;
1461
1462#ifdef MP_DEBUG
1463    fprintf(stderr, "set_input_fragment: exiting, last_frag = %d, fbtbc = %d\n",
1464            link->last_frag, link->fbtbc);
1465#endif
1466
1467    return MP_Success;
1468}
1469
1470/*******************************************************************************
1471 *
1472 * consumes input bytes; knows nothing about messages!
1473 *
1474 *******************************************************************************/
1475#ifdef __STDC__
1476static MP_Status_t skip_input_bytes(MP_Link_pt link,
1477                                    long       cnt)
1478#else
1479static MP_Status_t skip_input_bytes(link, cnt)
1480    MP_Link_pt link;
1481    long       cnt;
1482#endif
1483{
1484    int current;
1485
1486    while (cnt > 0) {
1487        current = (int)link->in_boundry - (int)link->in_finger;
1488        if (current == 0) {
1489            if (!fill_input_buf(link))
1490                return MP_Failure;
1491        } else {
1492            current = cnt < current ? cnt : current;
1493            link->in_finger += current;
1494            cnt -= current;
1495        }
1496    }
1497
1498    return MP_Success;
1499}
1500
1501
Note: See TracBrowser for help on using the repository browser.