terom@53: #include "irc_client.h" terom@53: #include "log.h" terom@53: terom@53: #include terom@53: #include terom@53: terom@53: err_t irc_client_create (struct irc_client **client_ptr, struct error_info *err) terom@53: { terom@53: struct irc_client *client; terom@53: terom@53: // allocate terom@53: if ((client = calloc(1, sizeof(*client))) == NULL) terom@53: return SET_ERROR(err, ERR_CALLOC); terom@53: terom@53: // init terom@53: TAILQ_INIT(&client->networks); terom@53: terom@53: // ok terom@53: *client_ptr = client; terom@53: terom@53: return SUCCESS; terom@53: } terom@53: terom@53: void irc_client_destroy (struct irc_client *client) terom@53: { terom@53: struct irc_net *next = TAILQ_FIRST(&client->networks), *net; terom@53: terom@53: // our networks terom@53: while (next) { terom@53: net = next; terom@53: next = TAILQ_NEXT(net, client_networks); terom@53: terom@53: irc_net_destroy(net); terom@53: } terom@53: terom@53: // ourselves terom@53: free(client); terom@53: } terom@53: terom@98: void irc_client_set_defaults (struct irc_client *client, const struct irc_client_defaults *defaults) terom@98: { terom@98: client->defaults = *defaults; terom@98: } terom@98: terom@98: #define APPLY_REGISTER_INFO_DEFAULT(out, value, def, _field_) ( \ terom@98: ((out)->register_info._field_ = ( \ terom@98: (value)->register_info._field_ ? (value)->register_info._field_ : ( \ terom@98: (def)->register_info._field_ \ terom@98: ) \ terom@98: )) == NULL \ terom@98: ) terom@98: terom@98: err_t irc_client_add_net (struct irc_client *client, struct irc_net **net_ptr, const struct irc_net_info *_net_info, struct error_info *err) terom@53: { terom@53: struct irc_net *net; terom@98: struct irc_net_info net_info = { terom@140: .ssl_cred = _net_info->ssl_cred, terom@98: }; terom@98: terom@98: // combine _net_info and defaults to get net_info terom@100: if (_net_info->raw_sock) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "raw_sock"); terom@100: terom@100: if ((net_info.network = _net_info->network) == NULL) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "network"); terom@100: terom@100: if ((net_info.hostname = _net_info->hostname) == NULL) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "hostname"); terom@100: terom@100: if ((net_info.service = (_net_info->service ? _net_info->service : ( terom@140: _net_info->ssl_cred ? client->defaults.service_ssl : client->defaults.service terom@100: ))) == NULL) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "service"); terom@100: terom@100: if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, nickname)) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "nickname"); terom@100: terom@100: if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, username)) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "username"); terom@100: terom@100: if (APPLY_REGISTER_INFO_DEFAULT(&net_info, _net_info, &client->defaults, realname)) terom@100: RETURN_SET_ERROR_STR(err, ERR_IRC_NET_INFO, "realname"); terom@53: terom@53: // create the new irc_chan struct terom@98: if (irc_net_create(&net, &net_info, err)) terom@63: return ERROR_CODE(err); terom@53: terom@53: // add to network list terom@53: TAILQ_INSERT_TAIL(&client->networks, net, client_networks); terom@53: terom@53: // ok terom@63: if (net_ptr) terom@63: *net_ptr = net; terom@53: terom@63: return SET_ERROR(err, SUCCESS); terom@53: } terom@53: terom@53: struct irc_net* irc_client_get_net (struct irc_client *client, const char *network) terom@53: { terom@53: struct irc_net *net = NULL; terom@53: terom@53: // look for it... terom@53: TAILQ_FOREACH(net, &client->networks, client_networks) { terom@53: if (strcasecmp(net->info.network, network) == 0) terom@53: // found it terom@53: return net; terom@53: } terom@53: terom@53: // no such network terom@53: return NULL; terom@53: } terom@53: terom@55: struct irc_chan* irc_client_get_chan (struct irc_client *client, const char *network, const char *channel) terom@55: { terom@55: struct irc_net *net; terom@55: terom@55: // lookup network terom@55: if ((net = irc_client_get_net(client, network)) == NULL) terom@55: return NULL; terom@55: terom@55: // and then return channel lookup terom@55: return irc_net_get_chan(net, channel); terom@55: } terom@55: terom@53: err_t irc_client_quit (struct irc_client *client, const char *message) terom@53: { terom@53: struct irc_net *net; terom@53: err_t err; terom@53: terom@53: // quit each network terom@53: TAILQ_FOREACH(net, &client->networks, client_networks) { terom@53: if ((err = irc_net_quit(net, message))) { terom@53: log_err(err, "irc_net_quit: %s [%s]", net->info.network, message); terom@53: terom@53: // XXX: destroy it? terom@53: } terom@53: } terom@53: terom@53: // state terom@53: client->quitting = true; terom@53: terom@53: // ok terom@53: return SUCCESS; terom@53: }