terom@25: #include "irc_net.h" terom@25: #include "log.h" terom@25: terom@25: #include terom@26: #include terom@25: terom@27: static void irc_net_conn_registered (struct irc_conn *conn, void *arg) terom@27: { terom@27: struct irc_net *net = arg; terom@27: struct irc_chan *chan = NULL; terom@27: err_t err; terom@27: terom@27: (void) conn; terom@27: terom@27: // join our channels terom@27: TAILQ_FOREACH(chan, &net->channels, node) { terom@27: if ((err = irc_chan_join(chan))) terom@27: // XXX: fuck... terom@27: FATAL_ERR(err, "irc_chan_join failed"); terom@27: } terom@27: } terom@27: terom@27: /** terom@27: * Our irc_conn_callbacks list terom@27: */ terom@27: struct irc_conn_callbacks _conn_callbacks = { terom@27: .on_registered = &irc_net_conn_registered, terom@27: }; terom@27: terom@25: err_t irc_net_create (struct irc_net **net_ptr, const struct irc_net_info *info, struct error_info *err) terom@25: { terom@25: struct irc_net *net; terom@28: struct sock_stream *sock = NULL; terom@25: terom@25: // allocate terom@25: if ((net = calloc(1, sizeof(*net))) == NULL) terom@25: return SET_ERROR(err, ERR_CALLOC); terom@25: terom@26: // initialize terom@26: TAILQ_INIT(&net->channels); terom@26: terom@25: // XXX: over-simplified blocking connect terom@25: if (info->use_ssl) { terom@25: log_info("connecting to [%s]:%s using SSL", info->hostname, info->service); terom@25: terom@25: if (sock_ssl_connect(&sock, info->hostname, info->service, err)) terom@25: goto error; terom@25: terom@25: } else { terom@25: log_info("connecting to [%s]:%s", info->hostname, info->service); terom@25: terom@25: if (sock_tcp_connect(&sock, info->hostname, info->service, err)) terom@25: goto error; terom@25: terom@25: } terom@25: terom@25: // create the irc connection state terom@27: if (irc_conn_create(&net->conn, sock, &_conn_callbacks, net, err)) terom@27: goto error; terom@27: terom@27: // register terom@28: log_info("connected, registering"); terom@28: terom@27: if ((ERROR_CODE(err) = irc_conn_register(net->conn, &info->register_info))) terom@25: goto error; terom@25: terom@25: // ok terom@25: *net_ptr = net; terom@25: terom@25: return SUCCESS; terom@25: terom@25: error: terom@28: // cleanup terom@28: if (net->conn) terom@28: // irc_conn takes care of the socket as well terom@28: irc_conn_destroy(net->conn); terom@28: terom@28: else if (sock) terom@28: // we need to clean up the socket ourself terom@28: sock_stream_release(sock); terom@28: terom@28: // release our state terom@28: free(net); terom@25: terom@25: return ERROR_CODE(err); terom@25: } terom@25: terom@26: struct irc_chan* irc_net_add_chan (struct irc_net *net, const struct irc_chan_info *info) terom@26: { terom@26: struct irc_chan *chan; terom@26: struct error_info err; terom@26: terom@26: // create the new irc_chan struct terom@26: if (irc_chan_create(&chan, net, info, &err)) terom@26: // XXX: we lose error info terom@26: return NULL; terom@26: terom@26: // add to network list terom@26: TAILQ_INSERT_TAIL(&net->channels, chan, node); terom@27: terom@27: // currently connected? terom@27: if (net->conn && net->conn->registered) { terom@27: // then join terom@27: if ((ERROR_CODE(&err) = irc_chan_join(chan))) terom@27: // XXX terom@27: return NULL; terom@27: } terom@26: terom@26: // ok, return terom@26: return chan; terom@26: } terom@26: terom@26: struct irc_chan* irc_net_get_chan (struct irc_net *net, const char *channel) terom@26: { terom@26: struct irc_chan *chan = NULL; terom@26: terom@26: // look for it... terom@26: TAILQ_FOREACH(chan, &net->channels, node) { terom@26: if (strcasecmp(chan->info.channel, channel) == 0) terom@26: // found it terom@26: return chan; terom@26: } terom@26: terom@26: // no such channel terom@26: return NULL; terom@26: terom@26: } terom@26: