$Log$
+Revision 1.15 2001/08/23 13:14:53 brian
+* Changed type on CxMsLoad() from (const char *) to (long unsigned int) to
+ make things more intuitive (and less apt for failure)
+* Vastly improved library interface, removed plenty of memory leaks.
+* Library _should_ be thread-safe, but I haven't tested it. If anyone's
+ brave, they're welcome to.
+* Library is almost completely stable now. At this point, I am blaming
+ most of its faults on Infusion. ;)
+
Revision 1.14 2001/06/13 15:06:44 brian
* Added distfiles for FreeBSD. To create a FreeBSD package, do this:
make install
Revision 1.2 2001/02/07 22:41:51 brian
* Updated ChangeLog to conform to Citadel/UX standards (kinda) :)
+
int cmd; // Command sent from server. [9xx]
char session[10]; // Optional session id.
- void (*Function)(void *); // Function to call upon success.
+ void (*Function)(int, void *); // Function to call upon success.
struct _Cmd_Callback *next;
#define MSGS_SEARCH 3 // *Unsupported* Search room for ...? .
CXLIST CxMsInfo(int, CXLIST);
CXLIST CxMsList(int, int,int);
-int CxMsLoad(int, const char *, int, MESGINFO *);
+int CxMsLoad(int, unsigned long int, int, MESGINFO *);
int CxMsSaveOk(int, const char *);
int CxMsSave(int, MESGINFO);
void CxMsMark(int, long unsigned int );
** _CxFiHook(): We will hook ourselves into the Transport layer to
** handle incoming file transfers.
**/
-void _CxFiHook(void *data) {
+void _CxFiHook(int cxid, void *data) {
DPF((DFA, "Message received"));
}
g_CxSemaphore = 0;
static CXCBHNDL _CbHandles = 0;
static char g_CxClientName[32] = "";
-static int _CxCallback(int cmd, void *data);
+static int _CxCallback(int, int, void *);
static void timeout() {}
static void _CxClSend( int, const char * );
-static int _CxClRecv( int, int*, char * );
+static int _CxClRecv( int, int*, char *, int );
/**
** CXTBL: Connection handle table. Use this to make libCxClient thread-safe, and allow
if( s ) {
DPF((DFA,"-> recv"));
- _CxClRecv( e->_sock, &(e->semaphore), buf );
+ _CxClRecv( e->_sock, &(e->semaphore), buf, id );
if(g_CxClientName[0]) {
sprintf(buf,"IDEN 1|1|100|CX/%s (%s)|",VERSION, g_CxClientName);
} else {
- sprintf(buf,"IDEN 1|1|100|CX/%s (unknown)|",VERSION);
+ sprintf(buf,"IDEN 1|1|100|CX/%s|",VERSION);
}
_CxClSend(s, buf);
- _CxClRecv(e->_sock, &(e->semaphore), buf);
+ _CxClRecv(e->_sock, &(e->semaphore), buf, id);
+
_CxClSend(s, "ASYN 1");
- rc = _CxClRecv(e->_sock, &(e->semaphore), buf);
+ rc = _CxClRecv(e->_sock, &(e->semaphore), buf, id);
/**
** If the server doesn't support Asnychronous mode, then
** we shouldn't try to be asynchronous...
**/
if(CHECKRC(rc, RC_OK)) {
+ DPF((DFA,":: Server in ASYNCHRONOUS mode."));
e->asynMode = 1;
-// g_CxAsynMode = 1;
} else {
+ DPF((DFA,":: ASYNCHRONOUS mode not supported."));
e->asynMode = 0;
-// g_CxAsynMode = 0;
}
/**
** _CxClRecv(): REAL receive.
**/
static
-int _CxClRecv( int sock, int *semaphore, char *s ) {
+int _CxClRecv( int sock, int *semaphore, char *s, int cxid ) {
char substr[4];
int i, tmp;
** If the server has told us a secret...
**/
if(CHECKRC(i, RC_ASYNCMSG)) {
- DPF((DFA,"Preparing to process async message"));
+ DPF((DFA,"Preparing to process async message on CXID"));
/**
** Do we have ANY callbacks defined?
/**
** Pass data to callback function, if appropriate.
**/
- if(_CxCallback(i, s)) {
+ if(_CxCallback(i, cxid, s)) {
/**
** ... Callback has failed. We need to
**/
/** INCOMPLETE **/
+ goto RETRY_RECV;
+ } else {
+ return( 000 );
}
- goto RETRY_RECV;
-
} else {
/** INCOMPLETE **/
+ goto RETRY_RECV;
}
}
}
DPF((DFA,"Preparing to receive on %d", e->_sock));
- return(_CxClRecv( e->_sock, &(e->semaphore), s ));
+ return(_CxClRecv( e->_sock, &(e->semaphore), s, id ));
}
/**
CXCBHNDL CxClCbExists(int cmd) {
CXCBHNDL x;
- return(0);
DPF((DFA,"[_CbHandles] @0x%08x", _CbHandles));
x = _CbHandles;
while( x ) {
int CxClCbRegister(int cmd, void *func) {
CXCBHNDL new;
- return(0);
-
DPF((DFA, "Registering callback for '%d' (@0x%08x)", cmd, func));
new = 0;
void CxClCbShutdown() {
CXCBHNDL x, y;
- return;
-
DPF((DFA,"Shutting down callback subsystem"));
x = _CbHandles;
while( x ) {
** _CxCallback(): Execute a callback.
**/
static
-int _CxCallback(int cmd, void *data) {
+int _CxCallback(int cmd, int cxid, void *data) {
CXCBHNDL cb;
- return(0);
-
DPF((DFA, "Executing callback %d", cmd));
cb = CxClCbExists(cmd);
- if(cb) cb->Function(data);
+ if(cb) cb->Function(cxid, data);
else return(1);
return(0);
**
** CLIENT MUST free(toret.body) MANUALLY!!!!
**/
-int CxMsLoad(int id, const char *mid, int preserve_newlines, MESGINFO *toret) {
+int CxMsLoad(int id, unsigned long int mid, int preserve_newlines, MESGINFO *toret) {
char buf[255], *newline="\n";
int rc, message_contents = 0, line_width;
- DPF((DFA,"Loading message \"%s\"",mid));
+ DPF((DFA,"Loading message \"%ld\"",mid));
toret->message_id = 0;
toret->author[0] = 0;
toret->rcpt[0] = 0;
toret->room[0] = 0;
toret->subject[0] = 0;
- sprintf(buf,"MSG2 %s",mid);
+ sprintf(buf,"MSG2 %ld",mid);
CxClSend(id, buf);
rc = CxClRecv(id, buf);
if(CHECKRC(rc, RC_LISTING) ) {
DPF((DFA,"Serializing '%s'",s));
- for (ap = argv; (*ap = (char *)strsep(&s, "|")) != NULL;) {
+ for (ap = argv; (*ap = (char *)strsep((char **)&s, "|")) != NULL;) {
if (++ap >= &argv[50]) {
break;
}
toret = (EXPRMESG *) CxMalloc( sizeof(EXPRMESG) );
bzero( &toret, sizeof(EXPRMESG) );
- CxSerialize( buf, &Ser );
+ CxSerialize( buf, (char **)&Ser );
toret->more_follows = atoi( Ser[0] );
toret->timestamp = (time_t) strtoul( Ser[1], 0, 10 );
char buf[512], *user_buf, *data_buf;
int rc;
- DPF((DFA, "Received RC_901 message"));
+ DPF((DFA, "*ASYN* Received RC_901 message on CXID %d", id));
DPF((DFA, "Raw data: %s\n", (char *)data));
rc = CxClRecv(id, buf);
**/
if(CHECKRC(rc, RC_LISTING)) {
do {
- rc = CxClRecv( id, buf);
+ rc = CxClRecv( id, buf );
if(rc<0) {
realloc(data_buf, strlen(data_buf)+strlen(buf));
strcat(data_buf, buf);
}
} while(rc < 0);
}
+
+ /**
+ ** Pass this information off to the user's function.
+ **/
_MiExpFunc(user_buf, data_buf);
CxFree(user_buf);
CxFree(data_buf);
** room's information structure.
**/
if(CHECKRC(rc, RC_OK)) {
- CxSerialize(buf, &g_Ser);
+ CxSerialize(buf, (char **) &g_Ser);
room_info = (ROOMINFO *)CxMalloc(sizeof(ROOMINFO));
strcpy(room_info->name, g_Ser[0]);
rc = CxClRecv(id, buf);
if(CHECKRC(rc, RC_OK)) {
- CxSerialize(buf, &g_Ser);
+ CxSerialize(buf, (char **) &g_Ser);
room_info = (ROOMINFO *)CxMalloc(sizeof(ROOMINFO));
strcpy(room_info->name, g_Ser[0]);
if( CHECKRC(rc, RC_OK) ) {
user_info = (USERINFO *)CxMalloc(sizeof(USERINFO));
- CxSerialize(buf, &g_Ser);
+ CxSerialize(buf, (char **) &g_Ser);
strcpy(user_info->username, g_Ser[0]);
user_info->system.access_level = atoi(g_Ser[1]);
user_info->system.times_called = atol(g_Ser[2]);