Linux HLSW LAN Master
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
4.1 KiB

  1. /***************************************************************************
  2. * Copyright (C) 11/2006 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <netinet/ip.h>
  27. #include <arpa/inet.h>
  28. #include "configfile.h"
  29. #include "list.h"
  30. #include "event.h"
  31. #include "scanner.h"
  32. #include "logging.h"
  33. #include "netpkt.h"
  34. #include "gamelist.h"
  35. #define HLSW_HEADER "\xFF\xFF\xFF\xFFHLSWLANSEARCH"
  36. #define HLSW_HEADER_LEN 0x11
  37. #define HLSW_ENTRY_LEN 10
  38. #define MAX_PKT_LEN (HLSW_HEADER_LEN + HLSW_ENTRY_LEN * 140)
  39. static LIST_HEAD(master_pkt_list);
  40. static int serverlist_add_game(struct game_entry *entry)
  41. {
  42. int found = 0;
  43. struct net_pkt *pkt;
  44. list_for_each_entry(pkt, &master_pkt_list, list) {
  45. if (pkt->size <= (MAX_PKT_LEN - HLSW_ENTRY_LEN)) {
  46. found = 1;
  47. break;
  48. }
  49. }
  50. if (!found) {
  51. pkt = malloc(sizeof(struct net_pkt) + MAX_PKT_LEN);
  52. if (pkt == NULL) {
  53. log_print(LOG_WARN, "serverlist_add_game(): out of memory");
  54. return -1;
  55. }
  56. memcpy(pkt->buf, HLSW_HEADER, HLSW_HEADER_LEN);
  57. pkt->size = HLSW_HEADER_LEN;
  58. list_add(&pkt->list, &master_pkt_list);
  59. }
  60. memcpy((void *)&pkt->buf + pkt->size, &entry->gameid, HLSW_ENTRY_LEN);
  61. pkt->size += HLSW_ENTRY_LEN;
  62. return 0;
  63. }
  64. static int serverlist_refresh(void *privdata)
  65. {
  66. int timeout = (int)privdata;
  67. struct net_pkt *pkt, *tmp;
  68. list_for_each_entry_safe(pkt, tmp, &master_pkt_list, list) {
  69. list_del(&pkt->list);
  70. free(pkt);
  71. }
  72. gamelist_gc_and_dump(serverlist_add_game, timeout);
  73. return 0;
  74. }
  75. static int server_handler(int fd, void *privdata)
  76. {
  77. struct sockaddr_in client;
  78. unsigned char buf[32];
  79. unsigned int i = sizeof(client);
  80. int ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&client, &i);
  81. if (ret <= 0) {
  82. log_print(LOG_WARN, "server_handler(): recvfrom()");
  83. return 0;
  84. }
  85. if (memcmp(buf, HLSW_HEADER, HLSW_HEADER_LEN))
  86. return 0;
  87. struct net_pkt *pkt;
  88. list_for_each_entry(pkt, &master_pkt_list, list)
  89. sendto(fd, pkt->buf, pkt->size, 0, (struct sockaddr *)&client, sizeof(client));
  90. return 0;
  91. }
  92. int server_init()
  93. {
  94. int sock = socket(PF_INET, SOCK_DGRAM, 0);
  95. if (sock < 0) {
  96. log_print(LOG_ERROR, "server_init(): socket()");
  97. return -1;
  98. }
  99. struct sockaddr_in src;
  100. char *addr = config_get_string("global", "master_src", "0.0.0.0:7140");
  101. if (parse_saddr(addr, &src) != 0) {
  102. log_print(LOG_ERROR, "server_init(): invalid master_src '%s'", addr);
  103. return -1;
  104. }
  105. if (bind(sock, (struct sockaddr *)&src, sizeof(src)) < 0) {
  106. log_print(LOG_ERROR, "server_init(): bind()");
  107. return -1;
  108. }
  109. event_add_readfd(sock, server_handler, NULL);
  110. struct timeval tv;
  111. tv.tv_sec = config_get_int("global", "serverlist_refresh", 5);
  112. tv.tv_usec = 0;
  113. int timeout = config_get_int("global", "serverlist_timeout", 180);
  114. event_add_timeout(&tv, serverlist_refresh, (void *)timeout);
  115. return 0;
  116. }