Пример #1
0
/**************************************************************************
  write wrapper function -vasc
**************************************************************************/
static int write_socket_data(struct connection *pc,
			     struct socket_packet_buffer *buf, int limit)
{
  int start, nput, nblock;

  if (is_server() && pc->server.is_closing) {
    return 0;
  }

  for (start=0; buf->ndata-start>limit;) {
    fd_set writefs, exceptfs;
    struct timeval tv;

    FC_FD_ZERO(&writefs);
    FC_FD_ZERO(&exceptfs);
    FD_SET(pc->sock, &writefs);
    FD_SET(pc->sock, &exceptfs);

    tv.tv_sec = 0; tv.tv_usec = 0;

    if (fc_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) {
      if (errno != EINTR) {
	break;
      } else {
	/* EINTR can happen sometimes, especially when compiling with -pg.
	 * Generally we just want to run select again. */
	continue;
      }
    }

    if (FD_ISSET(pc->sock, &exceptfs)) {
      connection_close(pc, _("network exception"));
      return -1;
    }

    if (FD_ISSET(pc->sock, &writefs)) {
      nblock=MIN(buf->ndata-start, MAX_LEN_PACKET);
      log_debug("trying to write %d limit=%d", nblock, limit);
      if((nput=fc_writesocket(pc->sock, 
			      (const char *)buf->data+start, nblock)) == -1) {
#ifdef NONBLOCKING_SOCKETS
	if (errno == EWOULDBLOCK || errno == EAGAIN) {
	  break;
	}
#endif
        connection_close(pc, _("lagging connection"));
        return -1;
      }
      start += nput;
    }
  }

  if (start > 0) {
    buf->ndata -= start;
    memmove(buf->data, buf->data+start, buf->ndata);
    pc->last_write = timer_renew(pc->last_write, TIMER_USER, TIMER_ACTIVE);
    timer_start(pc->last_write);
  }
  return 0;
}
Пример #2
0
/**************************************************************************
  Check for data received from the metaserver.
**************************************************************************/
static enum server_scan_status
get_metaserver_list(struct server_scan *scan)
{
  struct timeval tv;
  fd_set sockset;

  if (!scan || scan->sock < 0) {
    return SCAN_STATUS_ERROR;
  }

  tv.tv_sec = 0;
  tv.tv_usec = 0;
  FD_ZERO(&sockset);
  FD_SET(scan->sock, &sockset);

  switch (scan->meta.state) {
  case META_CONNECTING:
    if (fc_select(scan->sock + 1, NULL, &sockset, NULL, &tv) < 0) {
      scan->error_func(scan, fc_strerror(fc_get_errno()));
    } else if (FD_ISSET(scan->sock, &sockset)) {
      meta_send_request(scan);
    }
    /* Keep waiting. */
    return SCAN_STATUS_WAITING;
    break;
  case META_WAITING:
    if (fc_select(scan->sock + 1, &sockset, NULL, NULL, &tv) < 0) {
      scan->error_func(scan, fc_strerror(fc_get_errno()));
    } else if (FD_ISSET(scan->sock, &sockset)) {
      meta_read_response(scan);
      return SCAN_STATUS_PARTIAL;
    }
    /* Keep waiting. */
    return SCAN_STATUS_WAITING;
    break;
  case META_DONE:
    return SCAN_STATUS_DONE;
    break;
  default:
    break;
  }

  assert(0);
  return SCAN_STATUS_ERROR;
}
Пример #3
0
/**************************************************************************
  write wrapper function -vasc
**************************************************************************/
static int write_socket_data(struct connection *pc,
			     struct socket_packet_buffer *buf, int limit)
{
  int start, nput, nblock;

  if (pc->delayed_disconnect) {
    if (delayed_disconnect > 0) {
      return 0;
    } else {
      if (close_callback) {
	(*close_callback)(pc);
      }
      return -1;
    }
  }

  for (start=0; buf->ndata-start>limit;) {
    fd_set writefs, exceptfs;
    struct timeval tv;

    MY_FD_ZERO(&writefs);
    MY_FD_ZERO(&exceptfs);
    FD_SET(pc->sock, &writefs);
    FD_SET(pc->sock, &exceptfs);

    tv.tv_sec = 0; tv.tv_usec = 0;

    if (fc_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) {
      if (errno != EINTR) {
	break;
      } else {
	/* EINTR can happen sometimes, especially when compiling with -pg.
	 * Generally we just want to run select again. */
	continue;
      }
    }

    if (FD_ISSET(pc->sock, &exceptfs)) {
      if (delayed_disconnect > 0) {
	pc->delayed_disconnect = TRUE;
	return 0;
      } else {
	if (close_callback) {
	  (*close_callback)(pc);
	}
	return -1;
      }
    }

    if (FD_ISSET(pc->sock, &writefs)) {
      nblock=MIN(buf->ndata-start, MAX_LEN_PACKET);
      freelog(LOG_DEBUG,"trying to write %d limit=%d",nblock,limit);
      if((nput=fc_writesocket(pc->sock, 
			      (const char *)buf->data+start, nblock)) == -1) {
#ifdef NONBLOCKING_SOCKETS
	if (errno == EWOULDBLOCK || errno == EAGAIN) {
	  break;
	}
#endif
	if (delayed_disconnect > 0) {
	  pc->delayed_disconnect = TRUE;
	  return 0;
	} else {
	  if (close_callback) {
	    (*close_callback)(pc);
	  }
	  return -1;
	}
      }
      start += nput;
    }
  }

  if (start > 0) {

    buf->ndata -= start;


    memmove(buf->data, buf->data+start, buf->ndata);
    pc->last_write = renew_timer_start(pc->last_write,
				       TIMER_USER, TIMER_ACTIVE);
  }
  return 0;
}
Пример #4
0
/****************************************************************************
  A wrapper around read_socket_data() which also handles the case the
  socket becomes writeable and there is still data which should be sent
  to the server.

Returns:
    -1  :  an error occurred - you should close the socket
    -2  :  the connection was closed
    >0  :  number of bytes read
    =0  :  no data read, would block
****************************************************************************/
static int read_from_connection(struct connection *pc, bool block)
{
  for (;;) {
    fd_set readfs, writefs, exceptfs;
    int socket_fd = pc->sock;
    bool have_data_for_server = (pc->used && pc->send_buffer
                                 && 0 < pc->send_buffer->ndata);
    int n;
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = 0;

    FC_FD_ZERO(&readfs);
    FD_SET(socket_fd, &readfs);

    FC_FD_ZERO(&exceptfs);
    FD_SET(socket_fd, &exceptfs);

    if (have_data_for_server) {
      FC_FD_ZERO(&writefs);
      FD_SET(socket_fd, &writefs);
      n = fc_select(socket_fd + 1, &readfs, &writefs, &exceptfs,
                    block ? NULL : &tv);
    } else {
      n = fc_select(socket_fd + 1, &readfs, NULL, &exceptfs,
                    block ? NULL : &tv);
    }

    /* the socket is neither readable, writeable nor got an
     * exception */
    if (n == 0) {
      return 0;
    }

    if (n == -1) {
      if (errno == EINTR) {
        /* EINTR can happen sometimes, especially when compiling with -pg.
         * Generally we just want to run select again. */
        log_debug("select() returned EINTR");
        continue;
      }

      log_error("select() return=%d errno=%d (%s)",
                n, errno, fc_strerror(fc_get_errno()));
      return -1;
    }

    if (FD_ISSET(socket_fd, &exceptfs)) {
      return -1;
    }

    if (have_data_for_server && FD_ISSET(socket_fd, &writefs)) {
      flush_connection_send_buffer_all(pc);
    }

    if (FD_ISSET(socket_fd, &readfs)) {
      return read_socket_data(socket_fd, pc->buffer);
    }
  }
}
Пример #5
0
/**************************************************************************
  SDL-client main loop.
**************************************************************************/
Uint16 gui_event_loop(void *pData,
                      void (*loop_action)(void *pData),
                      Uint16 (*key_down_handler)(SDL_keysym Key, void *pData),
                      Uint16 (*key_up_handler)(SDL_keysym Key, void *pData),
                      Uint16 (*mouse_button_down_handler)(SDL_MouseButtonEvent *pButtonEvent, void *pData),
                      Uint16 (*mouse_button_up_handler)(SDL_MouseButtonEvent *pButtonEvent, void *pData),
                      Uint16 (*mouse_motion_handler)(SDL_MouseMotionEvent *pMotionEvent, void *pData))
{
    Uint16 ID;
    static struct timeval tv;
    static fd_set civfdset;
    Uint32 t_current, t_last_unit_anim, t_last_map_scrolling;
    Uint32 real_timer_next_call;
    static int result, schot_nr = 0;
    static char schot[32];

    ID = ID_ERROR;
    t_last_map_scrolling = t_last_unit_anim = real_timer_next_call = SDL_GetTicks();
    while (ID == ID_ERROR) {
        /* ========================================= */
        /* net check with 10ms delay event loop */
        if ((net_socket >= 0) || (ggz_socket >= 0)) {
            FD_ZERO(&civfdset);

            if (net_socket >= 0) {
                FD_SET(net_socket, &civfdset);
            }
            if (ggz_socket >= 0) {
                FD_SET(ggz_socket, &civfdset);
            }

            tv.tv_sec = 0;
            tv.tv_usec = 10000;/* 10ms*/

            result = fc_select(MAX(net_socket, ggz_socket) + 1, &civfdset, NULL, NULL, &tv);
            if (result < 0) {
                if (errno != EINTR) {
                    break;
                } else {
                    continue;
                }
            } else {
                if (result > 0) {
                    if ((net_socket >= 0) && FD_ISSET(net_socket, &civfdset)) {
                        SDL_PushEvent(pNet_User_Event);
                    }
                    if ((ggz_socket >= 0) && FD_ISSET(ggz_socket, &civfdset)) {
                        SDL_PushEvent(pGGZ_User_Event);
                    }
                }
            }
        } else { /* if connection is not establish */
            SDL_Delay(10);
        }
        /* ========================================= */

        t_current = SDL_GetTicks();

        if (t_current > real_timer_next_call) {
            real_timer_next_call = t_current + (real_timer_callback() * 1000);
        }

        if ((t_current - t_last_unit_anim) > UNITS_TIMER_INTERVAL) {
            if (autoconnect) {
                widget_info_counter++;
                SDL_PushEvent(pAnim_User_Event);
            } else {
                SDL_PushEvent(pAnim_User_Event);
            }

            t_last_unit_anim = SDL_GetTicks();
        }

        if (is_map_scrolling) {
            if ((t_current - t_last_map_scrolling) > MAP_SCROLL_TIMER_INTERVAL) {
                SDL_PushEvent(pMap_Scroll_User_Event);
                t_last_map_scrolling = SDL_GetTicks();
            }
        } else {
            t_last_map_scrolling = SDL_GetTicks();
        }

        if (widget_info_counter > 0) {
            SDL_PushEvent(pInfo_User_Event);
            widget_info_counter = 0;
        }

        /* ========================================= */

        if (loop_action) {
            loop_action(pData);
        }

        /* ========================================= */

        while (SDL_PollEvent(&Main.event) == 1) {

            switch (Main.event.type) {

            case SDL_QUIT:
                return MAX_ID;
                break;

            case SDL_KEYUP:
                switch (Main.event.key.keysym.sym) {
                /* find if Shifts are released */
                case SDLK_RSHIFT:
                    RSHIFT = FALSE;
                    break;
                case SDLK_LSHIFT:
                    LSHIFT = FALSE;
                    break;
                case SDLK_LCTRL:
                    LCTRL = FALSE;
                    break;
                case SDLK_RCTRL:
                    RCTRL = FALSE;
                    break;
                case SDLK_LALT:
                    LALT = FALSE;
                    break;
                default:
                    if(key_up_handler) {
                        ID = key_up_handler(Main.event.key.keysym, pData);
                    }
                    break;
                }
                break;

            case SDL_KEYDOWN:
                switch(Main.event.key.keysym.sym) {
                case SDLK_PRINT:
                    fc_snprintf(schot, sizeof(schot), "fc_%05d.bmp", schot_nr++);
                    log_normal(_("Making screenshot %s"), schot);
                    SDL_SaveBMP(Main.screen, schot);
                    break;

                case SDLK_RSHIFT:
                    /* Right Shift is Pressed */
                    RSHIFT = TRUE;
                    break;

                case SDLK_LSHIFT:
                    /* Left Shift is Pressed */
                    LSHIFT = TRUE;
                    break;

                case SDLK_LCTRL:
                    /* Left CTRL is Pressed */
                    LCTRL = TRUE;
                    break;

                case SDLK_RCTRL:
                    /* Right CTRL is Pressed */
                    RCTRL = TRUE;
                    break;

                case SDLK_LALT:
                    /* Left ALT is Pressed */
                    LALT = TRUE;
                    break;

                default:
                    if(key_down_handler) {
                        ID = key_down_handler(Main.event.key.keysym, pData);
                    }
                    break;
                }
                break;

            case SDL_MOUSEBUTTONDOWN:
                if(mouse_button_down_handler) {
                    ID = mouse_button_down_handler(&Main.event.button, pData);
                }
                break;

            case SDL_MOUSEBUTTONUP:
                if(mouse_button_up_handler) {
                    ID = mouse_button_up_handler(&Main.event.button, pData);
                }
                break;

            case SDL_MOUSEMOTION:
                if(mouse_motion_handler) {
                    ID = mouse_motion_handler(&Main.event.motion, pData);
                }
                break;

            case SDL_USEREVENT:
                switch(Main.event.user.code) {
                case NET:
                    input_from_server(net_socket);
                    break;
                case GGZ:
                    input_from_ggz(ggz_socket);
                    break;
                case ANIM:
                    update_button_hold_state();
                    animate_mouse_cursor();
                    draw_mouse_cursor();
                    break;
                case SHOW_WIDGET_INFO_LABBEL:
                    draw_widget_info_label();
                    break;
                case TRY_AUTO_CONNECT:
                    if (try_to_autoconnect()) {
                        pInfo_User_Event->user.code = SHOW_WIDGET_INFO_LABBEL;
                        autoconnect = FALSE;
                    }
                    break;
                case FLUSH:
                    unqueue_flush();
                    break;
                case MAP_SCROLL:
                    scroll_mapview(scroll_dir);
                    break;
                case EXIT_FROM_EVENT_LOOP:
                    return MAX_ID;
                    break;
                default:
                    break;
                }
                break;

            }
        }

        if (ID == ID_ERROR) {
            if (callbacks && callback_list_size(callbacks) > 0) {
                struct callback *cb = callback_list_get(callbacks, 0);
                callback_list_remove(callbacks, cb);
                (cb->callback)(cb->data);
                free(cb);
            }
        }
    }

    return ID;
}