implemented custom KeepConn Time Mode (+K <time>) and relay command for external...
[ircu2.10.12-pk.git] / ircd / s_bsd.c
index 00f7d8edc42ddba7005a0037bb8def01a6e72bed..542a41224a4c0f3143bc7b7082a4d58419d4a81c 100644 (file)
@@ -459,6 +459,34 @@ void close_connection(struct Client *cptr)
   }
 }
 
+/**
+ * Switches a client's connection over to a different, zombied client.
+ *
+ * @param source client to attach to zombied client
+ * @param target zombied client
+ */
+void connection_switch_to_client(struct Client *source, struct Client *target)
+{
+  assert(IsNotConn(target));
+  assert(MyConnect(source));
+  assert(-1 < cli_fd(source));
+  cli_connect(target) = cli_connect(source);
+  /* conveniently, this makes it much easier to get rid of source later on */
+  cli_from(target) = target;
+  LocalClientArray[cli_fd(source)] = target;
+
+  /* make main loop remove source soonish */
+  SetFlag(source, FLAG_DEADSOCKET);
+
+  /* need to copy over data from old client */
+  cli_user(target)->server = cli_user(source)->server;
+  strcpy(cli_yxx(target), cli_yxx(source));
+  cli_hopcount(target) = cli_hopcount(source);
+  cli_ip(target) = cli_ip(source);
+  strcpy(cli_username(target), cli_username(source));
+  strcpy(cli_user(target)->realhost, cli_user(source)->realhost);
+}
+
 /** Close all unregistered connections.
  * @param source Oper who requested the close.
  * @return Number of closed connections.
@@ -939,7 +967,9 @@ void client_sock_callback(struct Event* ev)
 
   assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr));
 
-  if (fallback) {
+  if (fallback && IsKeepConnEnabled(cptr)) {
+    zombie_client(&me, &me, cptr);
+  } else if (fallback) {
     const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : fallback;
     if (!msg)
       msg = "Unknown error";