* Copyright (c) 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)api_exch.c 4.1 (Berkeley) 12/4/88";
#include "../general/general.h"
static int sock
; /* Socket number */
static char whoarewe
[40] = "";
#define WHO_ARE_WE() fprintf(stderr, "(API %s) ", whoarewe);
static enum {CONTENTION
, SEND
, RECEIVE
} conversation
;
static struct exch_exch exch_state
;
static char ibuffer
[4000], *ibuf_next
, *ibuf_last
;
#define IBUFADDED(i) ibuf_last += (i)
#define IBUFAVAILABLE() (ibuf_last-ibuf_next)
#define IBUFFER() ibuffer
#define IBUFFREE() (ibuffer+sizeof ibuffer-ibuf_last-1)
#define IBUFGETBYTES(w,l) { memcpy(w, ibuf_next, l); ibuf_next += l; }
#define IBUFRESET() (ibuf_next = ibuf_last = ibuffer)
char obuffer
[4000], *obuf_next
;
#define OBUFADDBYTES(w,l) { memcpy(obuf_next, w, l); obuf_next += l; }
#define OBUFAVAILABLE() (obuf_next - obuffer)
#define OBUFFER() obuffer
#define OBUFRESET() obuf_next = obuffer
#define OBUFROOM() (obuffer+sizeof obuffer-obuf_next)
int length
= OBUFAVAILABLE();
if (write(sock
, OBUFFER(), length
) != length
) {
if ((count
= IBUFAVAILABLE()) != 0) {
IBUFGETBYTES(location
, count
);
if (ibuf_next
== ibuf_last
) {
if ((count
= read(sock
, IBUFFER(), IBUFFREE())) < 0) {
/* Reading past end-of-file */
fprintf(stderr
, "End of file read\r\n");
IBUFGETBYTES(location
, count
);
int exch
; /* opcode to decode */
case EXCH_EXCH_TURNAROUND
:
return "Request to Send";
sprintf(unknown
, "(Unknown exchange 0x%02x)", exch
&0xff);
* Send the exch structure, updating the sequnce number field.
if (OBUFROOM() < sizeof exch_state
) {
my_sequence
= (my_sequence
+1)&0xff;
exch_state
.my_sequence
= my_sequence
;
exch_state
.your_sequence
= your_sequence
;
OBUFADDBYTES((char *)&exch_state
, sizeof exch_state
);
* Receive the exch structure from the other side, checking
if (iget((char *)&exch_state
, sizeof exch_state
) == -1) {
if (conversation
!= CONTENTION
) {
if (exch_state
.your_sequence
!= my_sequence
) {
fprintf(stderr
, "Send sequence number mismatch.\n");
if (exch_state
.my_sequence
!= ((++your_sequence
)&0xff)) {
fprintf(stderr
, "Receive sequence number mismatch.\n");
your_sequence
= exch_state
.my_sequence
;
exch_state
.opcode
= EXCH_EXCH_TURNAROUND
;
if (send_state() == -1) {
if (receive_state() == -1) {
if (exch_state
.opcode
!= EXCH_EXCH_RTS
) {
fprintf(stderr
, "In CONTENTION state: ");
if (exch_state
.opcode
== EXCH_EXCH_TURNAROUND
) {
"Both sides tried to enter RECEIVE state.\n");
"Protocol error trying to enter RECEIVE state.\n");
exch_state
.opcode
= EXCH_EXCH_TURNAROUND
;
if (send_state() == -1) {
exch_state
.opcode
= EXCH_EXCH_RTS
;
if (send_state() == -1) {
if (receive_state() == -1) {
if (exch_state
.opcode
!= EXCH_EXCH_TURNAROUND
) {
fprintf(stderr
, "Conversation error - both sides in SEND state.\n");
if (conversation
!= RECEIVE
) {
if (enter_receive() == -1) {
if (receive_state() == -1) {
if (exch_state
.opcode
!= EXCH_EXCH_COMMAND
) {
fprintf(stderr
, "Expected a %s exchange, received a %s exchange.\n",
exch_to_ascii(EXCH_EXCH_COMMAND
), exch_to_ascii(exch_state
.opcode
));
return exch_state
.command_or_type
;
api_exch_incommand(command
)
if ((i
= api_exch_nextcommand()) == -1) {
fprintf(stderr
, "Expected API command 0x%x, got API command 0x%x.\n",
api_exch_outcommand(command
)
if (conversation
!= SEND
) {
if (enter_send() == -1) {
exch_state
.command_or_type
= command
;
exch_state
.opcode
= EXCH_EXCH_COMMAND
;
if (send_state() == -1) {
api_exch_outtype(type
, length
, location
)
if (conversation
!= SEND
) {
if (enter_send() == -1) {
exch_state
.opcode
= EXCH_EXCH_TYPE
;
exch_state
.command_or_type
= type
;
exch_state
.length
= netleng
;
if (send_state() == -1) {
if (OBUFROOM() > length
) {
OBUFADDBYTES(location
, length
);
if (write(sock
, location
, length
) != length
) {
api_exch_intype(type
, length
, location
)
if (conversation
!= RECEIVE
) {
if (enter_receive() == -1) {
if (receive_state() == -1) {
if (exch_state
.opcode
!= EXCH_EXCH_TYPE
) {
"Expected to receive a %s exchange, received a %s exchange.\n",
exch_to_ascii(EXCH_EXCH_TYPE
), exch_to_ascii(exch_state
.opcode
));
if (exch_state
.command_or_type
!= type
) {
fprintf(stderr
, "Expected type 0x%x, got type 0x%x.\n",
type
, exch_state
.command_or_type
);
if (exch_state
.length
!= netleng
) {
fprintf(stderr
, "Type 0x%x - expected length %d, received length %u.\n",
type
, length
, exch_state
.length
);
if (iget(location
, length
) == -1) {
api_exch_init(sock_number
, ourname
)
(void) strcpy(whoarewe
, ourname
); /* For error messages */
my_sequence
= your_sequence
= 0;
conversation
= CONTENTION
; /* We don't know which direction */