} *argv;
};
+char *dc_srv_local;
+
int dc_init(void);
void dc_cleanup(void);
void dc_disconnect(void);
int dc_handleread(void);
int dc_handlewrite(void);
int dc_connect(char *host);
-int dc_connectlocal(void);
+int dc_connectsync(char *host, struct dc_response **respbuf);
+int dc_connectsync2(char *host, int rev);
struct dc_intresp *dc_interpret(struct dc_response *resp);
void dc_freeires(struct dc_intresp *ires);
int dc_checkprotocol(struct dc_response *resp, int revision);
const char *dc_gethostname(void);
+int dc_getfd(void);
#endif
void *udata;
};
+int dc_convtty(int type, wchar_t *text, char **resp, void *data);
+int dc_convnone(int type, wchar_t *text, char **resp, void *data);
void dc_loginasync(char *username, int useauthless, int (*conv)(int, wchar_t *, char **, void *), void (*callback)(int, wchar_t *, void *), void *udata);
+int dc_login(char *username, int useauthless, int (*conv)(int, wchar_t *, char **, void *), wchar_t **reason);
struct dc_fnetnode *dc_findfnetnode(int id);
void dc_getfnlistasync(void (*callback)(int, void *), void *udata);
void dc_uimisc_handlenotify(struct dc_response *resp);
int family;
int sentcreds;
} servinfo;
+char *dc_srv_local;
static struct dc_response *makeresp(void)
{
{
if((ichandle = iconv_open("wchar_t", "utf-8")) == (iconv_t)-1)
return(-1);
+ dc_srv_local = sstrdup("");
initcmds();
return(0);
}
return(ret);
}
-static int dc_connectai(struct addrinfo *hosts)
+static int dc_connectai(struct addrinfo *hosts, struct qcmd **cnctcmd)
{
struct qcmd *qcmd;
int errnobak;
if((fd = socket(curhost->ai_family, curhost->ai_socktype, curhost->ai_protocol)) < 0)
{
errnobak = errno;
+ freeaddrinfo(hostlist);
+ hostlist = NULL;
errno = errnobak;
return(-1);
}
break;
}
}
- qcmd = makeqcmd(NULL);
- resetreader = 1;
+ if(state != -1)
+ {
+ qcmd = makeqcmd(NULL);
+ if(cnctcmd != NULL)
+ *cnctcmd = qcmd;
+ resetreader = 1;
+ } else {
+ free(hostlist);
+ hostlist = NULL;
+ }
return(fd);
}
-int dc_connect(char *host)
+static int dc_connect2(char *host, struct qcmd **cnctcmd)
{
struct addrinfo *ai;
+ struct qcmd *qcmd;
int ret;
- if(!host || !*host)
+ if(host == dc_srv_local)
+ ai = getlocalai();
+ else if(!host || !*host)
ai = defaulthost();
else
ai = resolvhost(host);
if(ai == NULL)
return(-1);
- if((ret = dc_connectai(ai)) != 0)
- freeaddrinfo(ai);
+ ret = dc_connectai(ai, &qcmd);
+ if((ret >= 0) && (cnctcmd != NULL))
+ *cnctcmd = qcmd;
return(ret);
}
-int dc_connectlocal(void)
+int dc_connect(char *host)
+{
+ return(dc_connect2(host, NULL));
+}
+
+int dc_connectsync(char *host, struct dc_response **respbuf)
{
- struct addrinfo *ai;
int ret;
+ struct qcmd *cc;
+ struct dc_response *resp;
- ai = getlocalai();
- if((ret = dc_connectai(ai)) != 0)
- freeaddrinfo(ai);
+ if((ret = dc_connect2(host, &cc)) < 0)
+ return(-1);
+ resp = dc_gettaggedrespsync(cc->tag);
+ if(resp == NULL) {
+ dc_disconnect();
+ return(-1);
+ }
+ if(respbuf == NULL)
+ dc_freeresp(resp);
+ else
+ *respbuf = resp;
+ return(ret);
+}
+
+int dc_connectsync2(char *host, int rev)
+{
+ int ret;
+ struct dc_response *resp;
+
+ if((ret = dc_connectsync(host, &resp)) < 0)
+ return(-1);
+ if(dc_checkprotocol(resp, rev))
+ {
+ dc_freeresp(resp);
+ dc_disconnect();
+ return(-1);
+ }
+ dc_freeresp(resp);
return(ret);
}
if((ires = dc_interpret(resp)) == NULL)
return(-1);
low = ires->argv[0].val.num;
- high = ires->argv[0].val.num;
+ high = ires->argv[1].val.num;
dc_freeires(ires);
if((revision < low) || (revision > high))
return(-1);
{
return(servinfo.hostname);
}
+
+int dc_getfd(void)
+{
+ return(fd);
+}
#include <pwd.h>
#include <string.h>
#include <stdio.h>
+#include <sys/poll.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
struct authmech *mech;
};
+struct synclogindata
+{
+ int aborted;
+ int err;
+ wchar_t *reason;
+};
+
struct gencbdata
{
void (*callback)(int resp, void *data);
}
};
-static int builtinconv(int type, wchar_t *text, char **resp, void *data)
+int dc_convtty(int type, wchar_t *text, char **resp, void *data)
{
char *buf, *pass;
return(1);
}
+int dc_convnone(int type, wchar_t *text, char **resp, void *data)
+{
+ return(1);
+}
+
static int logincallback(struct dc_response *resp)
{
int i;
data = smalloc(sizeof(*data));
if(conv == NULL)
- conv = builtinconv;
+ conv = dc_convtty;
data->conv = conv;
data->mech = NULL;
data->data = udata;
dc_queuecmd(logincallback, data, L"lsauth", NULL);
}
+static void synclogincb(int err, wchar_t *reason, struct synclogindata *data)
+{
+ if(data->aborted)
+ {
+ free(data);
+ return;
+ }
+ data->err = err;
+ if(reason == NULL)
+ data->reason = NULL;
+ else
+ data->reason = swcsdup(reason);
+}
+
+int dc_login(char *username, int useauthless, int (*conv)(int, wchar_t *, char **, void *), wchar_t **reason)
+{
+ int ret, abort;
+ struct synclogindata *dbuf;
+ struct pollfd pfd;
+
+ dbuf = smalloc(sizeof(*dbuf));
+ memset(dbuf, 0, sizeof(*dbuf));
+ dbuf->err = -1;
+ dc_loginasync(username, useauthless, conv, (void (*)(int, wchar_t *, void *))synclogincb, dbuf);
+ while(dbuf->err == -1)
+ {
+ pfd.fd = dc_getfd();
+ pfd.events = POLLIN;
+ if(dc_wantwrite())
+ pfd.events |= POLLOUT;
+ abort = 0;
+ if(poll(&pfd, 1, -1) < 0)
+ abort = 1;
+ if(!abort && (pfd.revents & POLLIN) && dc_handleread())
+ abort = 1;
+ if(!abort && (pfd.revents & POLLOUT) && dc_handlewrite())
+ abort = 1;
+ if(abort)
+ {
+ dbuf->aborted = 1;
+ return(-1);
+ }
+ }
+ if(reason != NULL)
+ *reason = dbuf->reason;
+ else if(dbuf->reason != NULL)
+ free(dbuf->reason);
+ ret = dbuf->err;
+ free(dbuf);
+ return(ret);
+}
+
static struct dc_fnetpeerdatum *finddatum(struct dc_fnetnode *fn, wchar_t *id)
{
struct dc_fnetpeerdatum *datum;