1*31890Sminshall /* 2*31890Sminshall * Copyright (c) 1984-1987 by the Regents of the 3*31890Sminshall * University of California and by Gregory Glenn Minshall. 4*31890Sminshall * 5*31890Sminshall * Permission to use, copy, modify, and distribute these 6*31890Sminshall * programs and their documentation for any purpose and 7*31890Sminshall * without fee is hereby granted, provided that this 8*31890Sminshall * copyright and permission appear on all copies and 9*31890Sminshall * supporting documentation, the name of the Regents of 10*31890Sminshall * the University of California not be used in advertising 11*31890Sminshall * or publicity pertaining to distribution of the programs 12*31890Sminshall * without specific prior permission, and notice be given in 13*31890Sminshall * supporting documentation that copying and distribution is 14*31890Sminshall * by permission of the Regents of the University of California 15*31890Sminshall * and by Gregory Glenn Minshall. Neither the Regents of the 16*31890Sminshall * University of California nor Gregory Glenn Minshall make 17*31890Sminshall * representations about the suitability of this software 18*31890Sminshall * for any purpose. It is provided "as is" without 19*31890Sminshall * express or implied warranty. 20*31890Sminshall */ 21*31890Sminshall 22*31890Sminshall #ifndef lint 23*31890Sminshall static char sccsid[] = "@(#)api_exch.c 1.8 (Berkeley) 07/17/87"; 24*31890Sminshall #endif /* not lint */ 25*31890Sminshall 2631460Sminshall #include <stdio.h> 2731460Sminshall 2831801Sminshall #include "../general/general.h" 2931801Sminshall 3031460Sminshall #include "api_exch.h" 3131460Sminshall 3231467Sminshall static int sock; /* Socket number */ 3331467Sminshall 3431474Sminshall static char whoarewe[40] = ""; 3531493Sminshall #define WHO_ARE_WE() fprintf(stderr, "(API %s) ", whoarewe); 3631474Sminshall 3731493Sminshall static enum {CONTENTION, SEND, RECEIVE } conversation; 3831493Sminshall 3931493Sminshall static struct exch_exch exch_state; 4031493Sminshall 4131493Sminshall static unsigned int 4231493Sminshall my_sequence, 4331493Sminshall your_sequence; 4431493Sminshall 4531499Sminshall static char ibuffer[4000], *ibuf_next, *ibuf_last; 4631460Sminshall #define IBUFADDED(i) ibuf_last += (i) 4731499Sminshall #define IBUFAVAILABLE() (ibuf_last-ibuf_next) 4831460Sminshall #define IBUFFER() ibuffer 4931499Sminshall #define IBUFFREE() (ibuffer+sizeof ibuffer-ibuf_last-1) 5031493Sminshall #define IBUFGETBYTES(w,l) { memcpy(w, ibuf_next, l); ibuf_next += l; } 5131460Sminshall #define IBUFRESET() (ibuf_next = ibuf_last = ibuffer) 5231460Sminshall 5331499Sminshall char obuffer[4000], *obuf_next; 5431460Sminshall #define OBUFADDBYTES(w,l) { memcpy(obuf_next, w, l); obuf_next += l; } 5531460Sminshall #define OBUFAVAILABLE() (obuf_next - obuffer) 5631460Sminshall #define OBUFFER() obuffer 5731460Sminshall #define OBUFRESET() obuf_next = obuffer 5831460Sminshall #define OBUFROOM() (obuffer+sizeof obuffer-obuf_next) 5931460Sminshall 6031460Sminshall 6131460Sminshall static int 6231460Sminshall outflush() 6331460Sminshall { 6431460Sminshall int length = OBUFAVAILABLE(); 6531460Sminshall 6631460Sminshall if (length != 0) { 6731460Sminshall if (write(sock, OBUFFER(), length) != length) { 6831493Sminshall WHO_ARE_WE(); 6931474Sminshall perror("write"); 7031460Sminshall return -1; 7131460Sminshall } 7231460Sminshall OBUFRESET(); 7331460Sminshall } 7431460Sminshall return 0; /* All OK */ 7531460Sminshall } 7631460Sminshall 7731460Sminshall 7831460Sminshall static int 7931499Sminshall iget(location, length) 8031499Sminshall char *location; 8131499Sminshall int length; 8231460Sminshall { 8331460Sminshall int i; 8431499Sminshall int count; 8531460Sminshall 8631460Sminshall if (OBUFAVAILABLE()) { 8731460Sminshall if (outflush() == -1) { 8831460Sminshall return -1; 8931460Sminshall } 9031460Sminshall } 9131499Sminshall if ((count = IBUFAVAILABLE()) != 0) { 9231499Sminshall if (count > length) { 9331499Sminshall count = length; 9431499Sminshall } 9531499Sminshall IBUFGETBYTES(location, count); 9631499Sminshall length -= count; 9731499Sminshall location += count; 9831460Sminshall } 9931499Sminshall while (length) { 10031499Sminshall if (ibuf_next == ibuf_last) { 10131499Sminshall IBUFRESET(); 10231499Sminshall } 10331499Sminshall if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) { 10431493Sminshall WHO_ARE_WE(); 10531474Sminshall perror("read"); 10631460Sminshall return -1; 10731460Sminshall } 10831499Sminshall if (count == 0) { 10931474Sminshall /* Reading past end-of-file */ 11031493Sminshall WHO_ARE_WE(); 11131493Sminshall fprintf(stderr, "End of file read\r\n"); 11231474Sminshall return -1; 11331474Sminshall } 11431499Sminshall IBUFADDED(count); 11531499Sminshall if (count > length) { 11631499Sminshall count = length; 11731499Sminshall } 11831499Sminshall IBUFGETBYTES(location, count); 11931499Sminshall length -= count; 12031499Sminshall location += count; 12131460Sminshall } 12231460Sminshall return 0; 12331460Sminshall } 12431460Sminshall 12531493Sminshall static char * 12631493Sminshall exch_to_ascii(exch) 12731493Sminshall int exch; /* opcode to decode */ 12831493Sminshall { 12931493Sminshall switch (exch) { 13031493Sminshall case EXCH_EXCH_COMMAND: 13131493Sminshall return "Command"; 13231493Sminshall case EXCH_EXCH_TYPE: 13331493Sminshall return "Type"; 13431493Sminshall case EXCH_EXCH_TURNAROUND: 13531493Sminshall return "Turnaround"; 13631493Sminshall case EXCH_EXCH_RTS: 13731493Sminshall return "Request to Send"; 13831493Sminshall default: 13931493Sminshall { 14031493Sminshall static char unknown[40]; 14131493Sminshall 14231493Sminshall sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff); 14331493Sminshall return unknown; 14431493Sminshall } 14531493Sminshall } 14631493Sminshall } 14731493Sminshall 14831493Sminshall /* 14931493Sminshall * Send the exch structure, updating the sequnce number field. 15031493Sminshall */ 15131493Sminshall 15231493Sminshall static int 15331493Sminshall send_state() 15431493Sminshall { 15531493Sminshall if (OBUFROOM() < sizeof exch_state) { 15631493Sminshall if (outflush() == -1) { 15731493Sminshall return -1; 15831493Sminshall } 15931493Sminshall } 16031498Sminshall my_sequence = (my_sequence+1)&0xff; 16131498Sminshall exch_state.my_sequence = my_sequence; 16231493Sminshall exch_state.your_sequence = your_sequence; 16331493Sminshall OBUFADDBYTES((char *)&exch_state, sizeof exch_state); 16431493Sminshall return 0; 16531493Sminshall } 16631493Sminshall 16731493Sminshall /* 16831493Sminshall * Receive the exch structure from the other side, checking 16931493Sminshall * sequence numbering. 17031493Sminshall */ 17131493Sminshall 17231493Sminshall static int 17331493Sminshall receive_state() 17431493Sminshall { 17531499Sminshall if (iget((char *)&exch_state, sizeof exch_state) == -1) { 17631499Sminshall return -1; 17731493Sminshall } 17831493Sminshall if (conversation != CONTENTION) { 17931493Sminshall if (exch_state.your_sequence != my_sequence) { 18031493Sminshall WHO_ARE_WE(); 18131493Sminshall fprintf(stderr, "Send sequence number mismatch.\n"); 18231493Sminshall return -1; 18331493Sminshall } 18431498Sminshall if (exch_state.my_sequence != ((++your_sequence)&0xff)) { 18531493Sminshall WHO_ARE_WE(); 18631493Sminshall fprintf(stderr, "Receive sequence number mismatch.\n"); 18731493Sminshall return -1; 18831493Sminshall } 18931493Sminshall } 19031498Sminshall your_sequence = exch_state.my_sequence; 19131493Sminshall return 0; 19231493Sminshall } 19331493Sminshall 19431493Sminshall static int 19531493Sminshall enter_receive() 19631493Sminshall { 19731493Sminshall switch (conversation) { 19831493Sminshall case CONTENTION: 19931493Sminshall exch_state.opcode = EXCH_EXCH_TURNAROUND; 20031493Sminshall if (send_state() == -1) { 20131493Sminshall return -1; 20231493Sminshall } 20331493Sminshall if (receive_state() == -1) { 20431493Sminshall return -1; 20531493Sminshall } 20631493Sminshall if (exch_state.opcode != EXCH_EXCH_RTS) { 20731493Sminshall WHO_ARE_WE(); 20831493Sminshall fprintf(stderr, "In CONTENTION state: "); 20931493Sminshall if (exch_state.opcode == EXCH_EXCH_TURNAROUND) { 21031493Sminshall fprintf(stderr, 21131493Sminshall "Both sides tried to enter RECEIVE state.\n"); 21231493Sminshall } else { 21331493Sminshall fprintf(stderr, 21431493Sminshall "Protocol error trying to enter RECEIVE state.\n"); 21531493Sminshall } 21631493Sminshall return -1; 21731493Sminshall } 21831493Sminshall break; 21931493Sminshall case SEND: 22031493Sminshall exch_state.opcode = EXCH_EXCH_TURNAROUND; 22131493Sminshall if (send_state() == -1) { 22231493Sminshall return -1; 22331493Sminshall } 22431493Sminshall break; 22531493Sminshall } 22631493Sminshall conversation = RECEIVE; 22731493Sminshall return 0; 22831493Sminshall } 22931493Sminshall 23031493Sminshall static int 23131493Sminshall enter_send() 23231493Sminshall { 23331493Sminshall switch (conversation) { 23431493Sminshall case CONTENTION: 23531493Sminshall exch_state.opcode = EXCH_EXCH_RTS; 23631493Sminshall if (send_state() == -1) { 23731493Sminshall return -1; 23831493Sminshall } 23931493Sminshall /* fall through */ 24031493Sminshall case RECEIVE: 24131493Sminshall if (receive_state() == -1) { 24231493Sminshall return -1; 24331493Sminshall } 24431493Sminshall if (exch_state.opcode != EXCH_EXCH_TURNAROUND) { 24531493Sminshall WHO_ARE_WE(); 24631493Sminshall fprintf(stderr, "Conversation error - both sides in SEND state.\n"); 24731493Sminshall return -1; 24831493Sminshall } 24931493Sminshall } 25031493Sminshall conversation = SEND; 25131493Sminshall return 0; 25231493Sminshall } 25331493Sminshall 25431467Sminshall int 25531493Sminshall api_exch_nextcommand() 25631467Sminshall { 25731493Sminshall if (conversation != RECEIVE) { 25831493Sminshall if (enter_receive() == -1) { 25931467Sminshall return -1; 26031467Sminshall } 26131467Sminshall } 26231493Sminshall if (receive_state() == -1) { 26331493Sminshall return -1; 26431493Sminshall } 26531493Sminshall if (exch_state.opcode != EXCH_EXCH_COMMAND) { 26631493Sminshall WHO_ARE_WE(); 26731493Sminshall fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n", 26831493Sminshall exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode)); 26931493Sminshall return -1; 27031493Sminshall } 27131493Sminshall return exch_state.command_or_type; 27231467Sminshall } 27331467Sminshall 27431467Sminshall 27531467Sminshall int 27631460Sminshall api_exch_incommand(command) 27731460Sminshall int command; 27831460Sminshall { 27931460Sminshall int i; 28031460Sminshall 28131493Sminshall if ((i = api_exch_nextcommand()) == -1) { 28231493Sminshall return -1; 28331460Sminshall } 28431460Sminshall if (i != command) { 28531493Sminshall WHO_ARE_WE(); 28631460Sminshall fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n", 28731460Sminshall command, i); 28831460Sminshall return -1; 28931460Sminshall } 29031460Sminshall return 0; 29131460Sminshall } 29231460Sminshall 29331460Sminshall 29431467Sminshall int 29531460Sminshall api_exch_outcommand(command) 29631460Sminshall int command; 29731460Sminshall { 29831493Sminshall if (conversation != SEND) { 29931493Sminshall if (enter_send() == -1) { 30031460Sminshall return -1; 30131460Sminshall } 30231460Sminshall } 30331493Sminshall exch_state.command_or_type = command; 30431493Sminshall exch_state.opcode = EXCH_EXCH_COMMAND; 30531493Sminshall if (send_state() == -1) { 30631493Sminshall return -1; 30731493Sminshall } else { 30831493Sminshall return 0; 30931493Sminshall } 31031460Sminshall } 31131460Sminshall 31231460Sminshall 31331467Sminshall int 31431460Sminshall api_exch_outtype(type, length, location) 31531460Sminshall int 31631460Sminshall type, 31731460Sminshall length; 31831460Sminshall char 31931460Sminshall *location; 32031460Sminshall { 32131801Sminshall int netleng = length; 32231460Sminshall 32331493Sminshall if (conversation != SEND) { 32431493Sminshall if (enter_send() == -1) { 32531460Sminshall return -1; 32631460Sminshall } 32731460Sminshall } 32831493Sminshall exch_state.opcode = EXCH_EXCH_TYPE; 32931493Sminshall exch_state.command_or_type = type; 33031493Sminshall exch_state.length = netleng; 33131493Sminshall if (send_state() == -1) { 33231493Sminshall return -1; 33331493Sminshall } 33431493Sminshall if (length) { 33531493Sminshall if (OBUFROOM() > length) { 33631493Sminshall OBUFADDBYTES(location, length); 33731493Sminshall } else { 33831493Sminshall if (outflush() == -1) { 33931493Sminshall return -1; 34031493Sminshall } 34131493Sminshall if (write(sock, location, length) != length) { 34231493Sminshall WHO_ARE_WE(); 34331493Sminshall perror("write"); 34431493Sminshall return -1; 34531493Sminshall } 34631460Sminshall } 34731460Sminshall } 34831493Sminshall return 0; 34931460Sminshall } 35031460Sminshall 35131460Sminshall 35231467Sminshall int 35331460Sminshall api_exch_intype(type, length, location) 35431460Sminshall int 35531460Sminshall type, 35631460Sminshall length; 35731460Sminshall char 35831460Sminshall *location; 35931460Sminshall { 36031801Sminshall int i, netleng = length; 36131460Sminshall 36231493Sminshall if (conversation != RECEIVE) { 36331493Sminshall if (enter_receive() == -1) { 36431460Sminshall return -1; 36531460Sminshall } 36631460Sminshall } 36731493Sminshall if (receive_state() == -1) { 36831460Sminshall return -1; 36931460Sminshall } 37031493Sminshall if (exch_state.opcode != EXCH_EXCH_TYPE) { 37131493Sminshall WHO_ARE_WE(); 37231493Sminshall fprintf(stderr, 37331493Sminshall "Expected to receive a %s exchange, received a %s exchange.\n", 37431493Sminshall exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode)); 37531493Sminshall return -1; 37631493Sminshall } 37731493Sminshall if (exch_state.command_or_type != type) { 37831493Sminshall WHO_ARE_WE(); 37931493Sminshall fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n", 38031493Sminshall type, exch_state.command_or_type); 38131493Sminshall return -1; 38231493Sminshall } 38331493Sminshall if (exch_state.length != netleng) { 38431460Sminshall fprintf(stderr, "Type 0x%x - expected length %d, received length %d.\n", 38531801Sminshall type, length, exch_state.length); 38631460Sminshall return -1; 38731460Sminshall } 38831499Sminshall if (iget(location, length) == -1) { 38931499Sminshall return -1; 39031460Sminshall } 39131460Sminshall return 0; 39231460Sminshall } 39331467Sminshall 39431467Sminshall int 39531493Sminshall api_exch_flush() 39631493Sminshall { 39731493Sminshall return outflush(); 39831493Sminshall } 39931493Sminshall 40031493Sminshall int 40131474Sminshall api_exch_init(sock_number, ourname) 40231467Sminshall int sock_number; 40331474Sminshall char *ourname; 40431467Sminshall { 40531467Sminshall sock = sock_number; 40631474Sminshall strcpy(whoarewe, ourname); /* For error messages */ 40731467Sminshall 40831493Sminshall my_sequence = your_sequence = 0; 40931493Sminshall 41031493Sminshall conversation = CONTENTION; /* We don't know which direction */ 41131493Sminshall 41231467Sminshall IBUFRESET(); 41331467Sminshall OBUFRESET(); 41431467Sminshall 41531467Sminshall return 0; 41631467Sminshall } 417