Browse Source

Bug fixes

Fix a potential random crash on non-Windows platforms.
Fix compatibility with some non-standard Shadowsocks and Shadowcsocks Android subscriptions.
Optimize codes.
Tindy X 6 years ago
parent
commit
78b4fec7d9
8 changed files with 70 additions and 38 deletions
  1. 25 23
      src/ini_reader.h
  2. 3 4
      src/interfaces.cpp
  3. 4 0
      src/main.cpp
  4. 16 5
      src/multithread.cpp
  5. 6 0
      src/multithread.h
  6. 11 5
      src/speedtestutil.cpp
  7. 2 1
      src/webget.cpp
  8. 3 0
      src/webserver_libevent.cpp

+ 25 - 23
src/ini_reader.h

@@ -107,6 +107,28 @@ public:
 
     ~INIReader() = default;
 
+    INIReader& operator=(const INIReader& src)
+    {
+        //copy contents
+        ini_content = src.ini_content;
+        //copy status
+        parsed = src.parsed;
+        current_section = src.current_section;
+        exclude_sections = src.exclude_sections;
+        include_sections = src.include_sections;
+        read_sections = src.read_sections;
+        section_order = src.section_order;
+        isolated_items_section = src.isolated_items_section;
+        //copy preferences
+        do_utf8_to_gbk = src.do_utf8_to_gbk;
+        store_any_line = src.store_any_line;
+        store_isolated_line = src.store_isolated_line;
+        allow_dup_section_titles = src.allow_dup_section_titles;
+        return *this;
+    }
+
+    INIReader(const INIReader &src) = default;
+
     std::string GetErrorString(int error)
     {
         switch(error)
@@ -158,26 +180,6 @@ public:
         isolated_items_section = section;
     }
 
-    INIReader& operator=(const INIReader& src)
-    {
-        //copy contents
-        ini_content = src.ini_content;
-        //copy status
-        parsed = src.parsed;
-        current_section = src.current_section;
-        exclude_sections = src.exclude_sections;
-        include_sections = src.include_sections;
-        read_sections = src.read_sections;
-        section_order = src.section_order;
-        isolated_items_section = src.isolated_items_section;
-        //copy preferences
-        do_utf8_to_gbk = src.do_utf8_to_gbk;
-        store_any_line = src.store_any_line;
-        store_isolated_line = src.store_isolated_line;
-        allow_dup_section_titles = src.allow_dup_section_titles;
-        return *this;
-    }
-
     /**
     *  @brief Parse INI content into mapped data structure.
     * If exclude sections are set, these sections will not be stored.
@@ -211,13 +213,13 @@ public:
         {
             last_error_index++;
             lineSize = strLine.size();
-            if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored
-                continue;
-            if(strLine[lineSize - 1] == '\r') //remove line break
+            if(lineSize && strLine[lineSize - 1] == '\r') //remove line break
             {
                 strLine = strLine.substr(0, lineSize - 1);
                 lineSize--;
             }
+            if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored
+                continue;
             if(strLine.find("=") != strLine.npos) //is an item
             {
                 if(inExcludedSection) //this section is excluded

+ 3 - 4
src/interfaces.cpp

@@ -141,7 +141,7 @@ int importItems(string_array &target)
         while(getline(ss, strLine, delimiter))
         {
             lineSize = strLine.size();
-            if(strLine[lineSize - 1] == '\r') //remove line break
+            if(lineSize && strLine[lineSize - 1] == '\r') //remove line break
             {
                 strLine = strLine.substr(0, lineSize - 1);
                 lineSize--;
@@ -1003,8 +1003,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
         }
         else
         {
-            YAML::Node yamlnode;
-            yamlnode = clash_base;
+            YAML::Node yamlnode = safe_get_clash_base();
             netchToClash(nodes, yamlnode, extra_group, target == "clashr", ext);
             output_content = YAML::Dump(yamlnode);
         }
@@ -1059,7 +1058,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
         else
         {
             INIReader ini;
-            ini = mellow_base;
+            ini = safe_get_mellow_base();
             netchToMellow(nodes, ini, rca, extra_group, ext);
             output_content = ini.ToString();
         }

+ 4 - 0
src/main.cpp

@@ -1,6 +1,7 @@
 #include <iostream>
 #include <string>
 #include <unistd.h>
+#include <signal.h>
 
 #include "interfaces.h"
 #include "version.h"
@@ -70,6 +71,9 @@ int main(int argc, char *argv[])
         return 1;
     }
     SetConsoleOutputCP(65001);
+#else
+    signal(SIGPIPE, SIG_IGN);
+    signal(SIGABRT, SIG_IGN);
 #endif // _WIN32
 
     SetConsoleTitle("subconverter " VERSION);

+ 16 - 5
src/multithread.cpp

@@ -1,13 +1,12 @@
-#include <mutex>
-
-#include "misc.h"
+#include "multithread.h"
 
 //safety lock for multi-thread
-typedef std::lock_guard<std::mutex> guarded_mutex;
-std::mutex on_emoji, on_rename, on_stream, on_time;
+std::mutex on_emoji, on_rename, on_stream, on_time, clash_base_mutex, mellow_base_mutex;
 
 extern string_array emojis, renames;
 extern string_array stream_rules, time_rules;
+extern YAML::Node clash_base;
+extern INIReader mellow_base;
 
 string_array safe_get_emojis()
 {
@@ -33,6 +32,18 @@ string_array safe_get_times()
     return time_rules;
 }
 
+YAML::Node safe_get_clash_base()
+{
+    guarded_mutex guard(clash_base_mutex);
+    return clash_base;
+}
+
+INIReader safe_get_mellow_base()
+{
+    guarded_mutex guard(mellow_base_mutex);
+    return mellow_base;
+}
+
 void safe_set_emojis(string_array &data)
 {
     guarded_mutex guard(on_emoji);

+ 6 - 0
src/multithread.h

@@ -2,7 +2,11 @@
 #define MULTITHREAD_H_INCLUDED
 
 #include <mutex>
+
+#include <yaml-cpp/yaml.h>
+
 #include "misc.h"
+#include "ini_reader.h"
 
 typedef std::lock_guard<std::mutex> guarded_mutex;
 
@@ -10,6 +14,8 @@ string_array safe_get_emojis();
 string_array safe_get_renames();
 string_array safe_get_streams();
 string_array safe_get_times();
+YAML::Node safe_get_clash_base();
+INIReader safe_get_mellow_base();
 void safe_set_emojis(string_array &data);
 void safe_set_renames(string_array &data);
 void safe_set_streams(string_array &data);

+ 11 - 5
src/speedtestutil.cpp

@@ -235,6 +235,8 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po
         ss = regReplace(ss, "(.*?)@(.*):(.*)", "$1|$2|$3");
         args = split(ss, "|");
         secret = split(urlsafe_base64_decode(args[0]), ":");
+        if(args.size() < 3 || secret.size() < 2)
+            return;
         method = secret[0];
         password = secret[1];
         server = args[1];
@@ -246,6 +248,8 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po
             return;
         ss = regReplace(urlsafe_base64_decode(ss), "(.*?):(.*?)@(.*):(.*)", "$1|$2|$3|$4");
         args = split(ss, "|");
+        if(args.size() < 4)
+            return;
         method = args[0];
         password = args[1];
         server = args[2];
@@ -325,16 +329,18 @@ void explodeSSAndroid(std::string ss, bool libev, std::string custom_port, int l
 
     for(unsigned int i = 0; i < json["nodes"].Size(); i++)
     {
-        json["nodes"][i]["remarks"] >> ps;
-        json["nodes"][i]["server"] >> server;
+        server = GetMember(json["nodes"][i], "server");
+        if(server.empty())
+            continue;
+        ps = GetMember(json["nodes"][i], "remarks");
         if(custom_port.size())
             port = custom_port;
         else
-            json["nodes"][i]["server_port"] >> port;
+            port = GetMember(json["nodes"][i], "server_port");
         if(ps == "")
             ps = server + ":" + port;
-        json["nodes"][i]["password"] >> password;
-        json["nodes"][i]["method"] >> method;
+        password = GetMember(json["nodes"][i], "password");
+        method = GetMember(json["nodes"][i], "method");
         plugin = GetMember(json["nodes"][i], "plugin");
         pluginopts = GetMember(json["nodes"][i], "plugin_opts");
 

+ 2 - 1
src/webget.cpp

@@ -4,11 +4,12 @@
 #include <curl/curl.h>
 
 #include "webget.h"
+#include "version.h"
 
 extern bool print_debug_info;
 
 //std::string user_agent_str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36";
-std::string user_agent_str = "subconverter/latest cURL/7.xx-DEV";
+std::string user_agent_str = "subconverter/" + std::string(VERSION) + " cURL/" + std::string(LIBCURL_VERSION);
 
 static int writer(char *data, size_t size, size_t nmemb, std::string *writerData)
 {

+ 3 - 0
src/webserver_libevent.cpp

@@ -194,6 +194,9 @@ int httpserver_bindsocket(std::string listen_address, int listen_port, int backl
 
     int one = 1;
     ret = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));
+#ifdef SO_NOSIGPIPE
+    ret = setsockopt(nfd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&one, sizeof(int));
+#endif
 
     struct sockaddr_in addr;
     memset(&addr, 0, sizeof(addr));