/* MaitreTarot. * (C) 2002 Philippe Brochard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #define player_set_type(t,a,b) (t)->type = (a); (t)->value=(b) /* ERR_NO:no error; ERR_CONNC:connexion error; ERR_OTH:other error */ typedef enum { ERR_NO = 0, ERR_CONNC = -1, ERR_OTH = -2 } error_t; /** * write some data on a channel * \brief write some data on a channel * \param channel_set channel set * \param channel_id channel ID * \param type type of data * \param data buffer where the data will be stored * \param len length of the buffer * \param msg_in output message when enter in player_read_data * \ * \return 0, or -1 if an error occured */ static gint player_write_data (libmt_channels_set_t * channels_set, gint channel_id, libmt_net_data_type_t * type, gpointer data, gint data_size, gchar * msg_in) { ssize_t ret; g_printerr ("%s\n", msg_in); if (libmt_write_type (channels_set, channel_id, type) == -1) return (-1); ret = libmt_channels_set_write (channels_set, channel_id, data, data_size); return ret; } /** * read some data on a channel * \brief read some data on a channel * \param channel_set channel set * \param channel_id channel ID * \param type type of data * \param data buffer where the data will be stored * \param len length of the buffer * \param msg_in output message when enter in player_read_data * \ * \return 0, or -1 if an error occured */ static gint player_read_data (libmt_channels_set_t * channels_set, gint channel_id, libmt_net_data_type_t * type, gpointer data, gint data_size, gchar * msg_in) { gpointer buf; gint l; g_printerr ("%s\n", msg_in); if (libmt_read_type (channels_set, channel_id, type) == -1) return (-1); l = 0; while (l == 0) { l = libmt_channels_set_has_enough_data_to_read (channels_set, channel_id, data_size); if (l == -1) return (-1); /* IRC and other channels here */ usleep (100); } buf = g_malloc (data_size); if (libmt_channels_set_read (channels_set, channel_id, buf, data_size) == -1) { g_free (buf); return (-1); } g_memmove (data, buf, data_size); g_free (buf); return (0); } gint libmt_client_connect_to_server (libmt_client_player_t * player, GString * host_name, guint16 port, gint id, gint version) { gpointer buf, p; gint gi; gint len[MAX_PLAYER]; gchar *nk; GError *err = NULL; libmt_net_data_type_t type; error_t ret; /* init the player */ player->net.client_id[0] = id; player->net.client_id[1] = version; /* connect to socket */ g_printerr ("Try to connect to socket\n"); g_printerr ("host: %s port: %d\n", host_name->str, port); player->net.sock = libmt_connect_to_socket (host_name->str, port, &err); if (player->net.sock == -1) { return ERR_OTH; } player->channels_set = libmt_channels_set_new (player->net.sock); if (player->channels_set == NULL) { return ERR_OTH; } g_printerr ("Connected to socket\n"); /* send client ID to server */ player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_ID, 0); ret = player_write_data (player->channels_set, 0, &type, player->net.client_id, sizeof (gint) * 2, "Try to send ID to server"); if (ret == -1) return ERR_CONNC; /* read id and version server */ ret = player_read_data (player->channels_set, 0, &type, player->net.server_id, sizeof (gint) * 2, "Try to read ID and version server"); if (ret == -1) return ERR_CONNC; /* read protocol version */ ret = player_read_data (player->channels_set, 0, &type, &(player->net.protocol_version), sizeof (gint), "Try to read protocol version"); if (ret == -1) return ERR_CONNC; /* write if client can use this protocol (1:yes 0:no) */ if (player->net.protocol_version == PROTOCOL) gi = 1; else gi = 0; player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_PROTOCOL, 0); ret = player_write_data (player->channels_set, 0, &type, &gi, sizeof (gint), "Try to send if client can use protocol"); if (ret == -1) return ERR_CONNC; if (player->net.protocol_version != PROTOCOL) return ERR_OTH; /* read place */ ret = player_read_data (player->channels_set, 0, &type, &(player->place), sizeof (gint), "Try to read place"); if (ret == -1) return ERR_CONNC; /* send nick_len */ player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_NICK_LEN, 0); ret = player_write_data (player->channels_set, 0, &type, &(player->nick[0]->len), sizeof (gint), "Try to send nick len"); if (ret == -1) return ERR_CONNC; /* send nick if len != 0 */ if (player->nick[0]->len > 0) { player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_NICK, 0); ret = player_write_data (player->channels_set, 0, &type, player->nick[0]->str, sizeof (gchar) * player->nick[0]->len, "Try to send ID nick"); if (ret == -1) return ERR_CONNC; } /* read all nick_len */ ret = player_read_data (player->channels_set, 0, &type, len, sizeof (gint) * player->nb_player, "Try to read all nick len"); if (ret == -1) return ERR_CONNC; /* read all nick name */ buf = g_malloc (sizeof (gchar) * (len[0] + len[1] + len[2] + len[3])); ret = player_read_data (player->channels_set, 0, &type, buf, sizeof (gchar) * (len[0] + len[1] + len[2] + len[3]), "Try to read all nicks"); if (ret == -1) { g_free (buf); return ERR_CONNC; } for (gi = 0, p = buf; gi < player->nb_player; gi++) { g_printerr ("len reseved = %d\n", len[gi]); nk = (gchar *) g_malloc0 (sizeof (gchar) * (len[gi] + 1)); g_memmove (nk, p, sizeof (gchar) * len[gi]); player->nick[gi] = g_string_new (""); g_string_sprintf (player->nick[gi], "%s", nk); p += player->nick[gi]->len; g_free (nk); } g_free (buf); g_printerr ("Connected!\n"); return ERR_NO; } void libmt_client_close_connexion (libmt_client_player_t * player) { gint gi; for (gi = 0; gi < player->nb_player; gi++) { if (player->nick[gi] != NULL) g_string_free (player->nick[gi], TRUE); } if (player->channels_set != NULL) libmt_channels_set_free (player->channels_set); if (player->client_private_data != NULL) g_free (player->client_private_data); if (player->net.sock != -1) close (player->net.sock); } gint libmt_client_get_hand_card (libmt_client_player_t * player) { gint gi; libmt_net_data_type_t type; error_t ret; for (gi = 0; gi < player->nb_player; gi++) { player->card_turn[gi] = -1; player->card_previous_turn[gi] = -1; } ret = player_read_data (player->channels_set, 0, &type, &(player->card), sizeof (gint) * player->nb_hand_card, "Try to get hand cards"); if (ret == -1) return ERR_CONNC; for (gi = 0; gi < player->nb_player; gi++) player->bid[gi] = -1; return ERR_NO; } gint libmt_client_get_bid (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, &(player->bid), sizeof (gint) * player->nb_player, "Try to get bids"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_get_bid_is_valide (libmt_client_player_t * player) { gint gi; libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, &gi, sizeof (gint), "Try to get if client have to make its bid"); if (ret == -1) return ERR_CONNC; return (gi); } gint libmt_client_have_to_make_bid (libmt_client_player_t * player) { gint gi; gint ok = 0; for (gi = 0; gi < player->nb_player; gi++) { if (LIBMT_BID_CMP (player->bid[gi], LIBMT_BID_PASSE) < 0 && ok == 0) { if (player->place == gi) ok = 1; } } return (ok); } gint libmt_client_send_bid (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_BID, 0); ret = player_write_data (player->channels_set, 0, &type, &(player->bid[player->place]), sizeof (gint), "Try to send bid"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_get_final_bid (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, &(player->bid), sizeof (gint) * player->nb_player, "Try to get final bids"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_is_someone_take (libmt_client_player_t * player) { gint gi; for (gi = 0; gi < player->nb_player; gi++) if (LIBMT_BID_CMP (player->bid[gi], LIBMT_BID_PASSE) > 0) return (1); return 0; } gint libmt_client_have_to_get_chien (libmt_client_player_t * player) { gint gi; gint bid = 0; g_printerr ("Client have to get chien ?\n"); for (gi = 0; gi < player->nb_player; gi++) { if (LIBMT_BID_CMP (player->bid[gi], bid) > 0) bid = player->bid[gi]; } if (LIBMT_BID_CMP (bid, LIBMT_BID_PASSE) >= 0 && LIBMT_BID_CMP (bid, LIBMT_BID_GARDE) <= 0) { g_printerr ("Yes\n"); return (1); } g_printerr ("No\n"); return 0; } gint libmt_client_is_the_taker (libmt_client_player_t * player) { gint gi; gint bid = 0; gint place = -1; g_printerr ("Player is the taker ?\n"); for (gi = 0; gi < player->nb_player; gi++) { if (LIBMT_BID_CMP (player->bid[gi], bid) > 0) { bid = player->bid[gi]; place = gi; } } if (player->place == place) { g_printerr ("Yes\n"); return (1); } g_printerr ("No\n"); return 0; } gint libmt_client_get_chien (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, player->chien, sizeof (gint) * player->nb_chien_card, "Try to get chien"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_send_chien (libmt_client_player_t * player) { gint ok = 0; libmt_net_data_type_t type; error_t ret; player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_CHIEN, 0); ret = player_write_data (player->channels_set, 0, &type, &(player->chien), sizeof (gint) * player->nb_chien_card, "Try to send chien"); if (ret == -1) return ERR_CONNC; ret = player_read_data (player->channels_set, 0, &type, &ok, sizeof (gint), "Try to read if chien is ok"); if (ret == -1) return ERR_CONNC; return (ok); } gint libmt_client_get_card (libmt_client_player_t * player) { gpointer buf; gint ok = 0; libmt_net_data_type_t type; error_t ret; buf = g_malloc (sizeof (gint) * player->nb_player * 2); ret = player_read_data (player->channels_set, 0, &type, buf, sizeof (gint) * player->nb_player * 2, "Try to read cards"); if (ret == -1) return ERR_CONNC; g_memmove (player->card_turn, buf, sizeof (gint) * player->nb_player); g_memmove (player->card_previous_turn, ((gint *) buf) + player->nb_player, sizeof (gint) * player->nb_player); g_free (buf); ret = player_read_data (player->channels_set, 0, &type, &ok, sizeof (gint), "Try to read if card is ok"); if (ret == -1) return ERR_CONNC; return (ok); } gint libmt_client_send_card (libmt_client_player_t * player) { gint ok = 0; libmt_net_data_type_t type; error_t ret; player_set_type (&type, LIBMT_NET_DATA_TYPE_GET_TURN_CARDS, 0); ret = player_write_data (player->channels_set, 0, &type, &(player->card_play), sizeof (gint), "Try to send card"); if (ret == -1) return ERR_CONNC; ret = player_read_data (player->channels_set, 0, &type, &(ok), sizeof (gint), "Try to read if card is ok"); if (ret == -1) return ERR_CONNC; return (ok); } gint libmt_client_get_last_turn (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, player->card_previous_turn, sizeof (gint) * player->nb_player, "Try to read last turn cards played"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_get_score (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; gpointer buf; gint i; buf = g_malloc (sizeof (gint) * (player->nb_player + 4)); ret = player_read_data (player->channels_set, 0, &type, buf, sizeof (gint) * (player->nb_player + 4), "Try to read scores"); if (ret == -1) { g_free (buf); return ERR_CONNC; } player->contract = ((gint *) buf)[0]; if ( ((gint *) buf)[1] == 1) player->taker_is_winner = TRUE; else player->taker_is_winner = FALSE; player->taker_score = ((gint *) buf)[2]; player->nb_oudler = ((gint *) buf)[3]; for (i = 0; i < player->nb_player; i++) { player->score[i] = ((gint *) buf)[i + 4]; } g_free (buf); return ERR_NO; } gint libmt_client_get_chien_at_end (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, player->chien, sizeof (gint) * player->nb_chien_card, "Try to get chien at end"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_send_replay_answer (libmt_client_player_t * player) { libmt_net_data_type_t type; error_t ret; player_set_type (&type, LIBMT_NET_DATA_TYPE_ACK_REPLAY, 0); ret = player_write_data (player->channels_set, 0, &type, &(player->replay), sizeof (gint), "Try to send replay answer"); if (ret == -1) return ERR_CONNC; return ERR_NO; } gint libmt_client_get_replay_answer (libmt_client_player_t * player) { gint ok = 0; libmt_net_data_type_t type; error_t ret; ret = player_read_data (player->channels_set, 0, &type, &ok, sizeof (gint), "Try to get replay answer from server"); if (ret == -1) return ERR_CONNC; return ok; }