func parseSchemeHostPort(arg string) (string, string, int, error) {
	var (
		scheme string
		host   string
		port   int
		err    error
	)
	remaining := arg
	if strings.Contains(remaining, "://") {
		parts := strings.SplitN(remaining, "://", 2)
		if len(parts) != 2 {
			return "", "", 0, fmt.Errorf("%v: Invalid hostname", arg)
		}
		scheme = parts[0]
		remaining = parts[1]
	} else {
		scheme = "https"
	}
	if strings.Contains(remaining, ":") {
		parts := strings.SplitN(remaining, ":", 2)
		if len(parts) != 2 {
			return "", "", 0, fmt.Errorf("%v: Invalid hostname", arg)
		}
		host = parts[0]
		port, err = strconv.Atoi(parts[1])
		if err != nil {
			return "", "", 0, fmt.Errorf("%v: Invalid hostname", arg)
		}
	} else {
		host = remaining
		port = 443
		if strings.Contains(host, "/") || strings.Contains(host, "&") || strings.Contains(host, "#") {
			return "", "", 0, fmt.Errorf("%v: Invalid hostname", arg)
		}
	}
	return scheme, host, port, nil
}
"https://localhost:8443" -> "https", "localhost", 8443, nil
package daemon
import (
	"bufio"
	"fmt"
	"github.com/fstab/h2c/cli/cmdline"
	"github.com/fstab/h2c/cli/rpc"
	"github.com/fstab/h2c/cli/util"
	"github.com/fstab/h2c/http2client"
	"github.com/fstab/h2c/http2client/frames"
	"io"
	"net"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"time"
)
func Run(sock net.Listener, frameTypesToBeDumped []frames.Type) error {
	var conn net.Conn
	var err error
	var h2c = http2client.New()
	if frameTypesToBeDumped != nil && len(frameTypesToBeDumped) > 0 {
		h2c.AddFilterForIncomingFrames(makeFrameFilter(DumpIncoming, frameTypesToBeDumped))
		h2c.AddFilterForOutgoingFrames(makeFrameFilter(DumpOutgoing, frameTypesToBeDumped))
	}
	stopOnSigterm(sock)
	for {
		if conn, err = sock.Accept(); err != nil {
			return fmt.Errorf("Error while waiting for commands: %v", err.Error())
			stop(sock)
		}
		go executeCommandAndCloseConnection(h2c, conn, sock)
	}
}
func makeFrameFilter(dumpFunction func(frames.Frame), frameTypesToBeDumped []frames.Type) func(frames.Frame) frames.Frame {
	return func(frame frames.Frame) frames.Frame {
		if util.SliceContainsFrameType(frameTypesToBeDumped, frame.Type()) {
			dumpFunction(frame)
		}
		return frame
	}
}
func close(sock io.Closer) {
	if err := sock.Close(); err != nil {
		fmt.Fprintf(os.Stderr, "Error terminating the h2c process: %v", err.Error())
	}
}
func stop(sock net.Listener) {
	close(sock)
	os.Exit(0)
}
func stopOnSigterm(sock net.Listener) {
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt)
	go func(c chan os.Signal) {
		<-c  
		stop(sock)
	}(sigc)
}
func execute(h2c *http2client.Http2Client, cmd *rpc.Command) (string, error) {
	switch cmd.Name {
	case cmdline.CONNECT_COMMAND.Name():
		return executeConnect(h2c, cmd)
	case cmdline.DISCONNECT_COMMAND.Name():
		return executeDisconnect(h2c, cmd)
	case cmdline.PID_COMMAND.Name():
		return strconv.Itoa(os.Getpid()), nil
	case cmdline.GET_COMMAND.Name():
		return executeGet(h2c, cmd)
	case cmdline.PUT_COMMAND.Name():
		return executePut(h2c, cmd)
	case cmdline.POST_COMMAND.Name():
		return executePost(h2c, cmd)
	case cmdline.PING_COMMAND.Name():
		return executePing(h2c, cmd)
	case cmdline.PUSH_LIST_COMMAND.Name():
		return executePushList(h2c, cmd)
	case cmdline.STREAM_INFO_COMMAND.Name():
		return executeStreamInfo(h2c, cmd)
	case cmdline.SET_COMMAND.Name():
		return h2c.SetHeader(cmd.Args[0], cmd.Args[1])
	case cmdline.UNSET_COMMAND.Name():
		return h2c.UnsetHeader(cmd.Args)
	default:
		return "", fmt.Errorf("%v: unknown command", cmd.Name)
	}
}
func executeConnect(h2c *http2client.Http2Client, cmd *rpc.Command) (string, error) {
	scheme, host, port, err := parseSchemeHostPort(cmd.Args[0])
	if err != nil {
		return "", err
	}
	return h2c.Connect(scheme, host, port)
}